结构体基础+线性表的的链式表示

1.认清结构体是如何定义的

#include<stdio.h>
#define DataType int

//1.
struct Node {
	DataType data;
	struct Node*next;
};
//2.
struct Node1 {
	DataType data;
	struct Node1*next;
}Node1,Node2[10];
//3.
typedef struct Node3 {
	DataType data;
	struct Node*next;
}ListNode;
//4
typedef struct Node4 {
	DataType data;
	struct Node*next;
}*LinkList, ListNode1;


int main()
{
	//1
	//标准的链表空间开辟:
	struct Node *p = (struct Node *)malloc(sizeof(struct Node));
	//结构体释放
	struct Node m = { 56,p };//直接定义m
	free(p);

	//2
	//是在上方就定义好了类似上方结构体m的东西
	//Node2[10]是一排结构体
	
	//3
	//就是可以用ListNode代替struct Node3 

	//4
	//用* LinkList代替struct Node4,需要借助类似3
	//里面的思想要好好考虑
	 LinkList n = (LinkList)malloc(sizeof(ListNode1));

	return 0;
}

2.线性表的链式存储

//线性表的链式表示
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define DataType int 

//单链表的定义
typedef struct Node {
	DataType data;
	struct Node*next;
}ListNode, *LinkList;


//头插法建立单链表,头结点head不是第一个节点,他的data里无数据
LinkList Creat_list1(LinkList head) {
	head = (LinkList)malloc(sizeof(ListNode));
	ListNode *node = NULL;
	int count = 0;
	head->next = NULL;
	node = head->next;
	printf("Input the node number: ");
	scanf("%d", &count);
	for (int i = 0; i < count; i++)
	{
		node = (LinkList)malloc(sizeof(ListNode));
		node->data = i;
		node->next = head->next;
		head->next = node;
	}
	return head;
}

//尾插法建立单链表
LinkList Creat_list2(LinkList head) {
	head = (LinkList)malloc(sizeof(ListNode));
	LinkList node = NULL;
	LinkList end = NULL;
	head->next = NULL;
	end = head; //head是不可能变化的,需要选取一个节点,不断让他等于链表的结尾                
	int count = 0;
	printf("Input node number: ");
	scanf("%d", &count);
	for (int i = 0; i < count; i++) {
		node = (LinkList)malloc(sizeof(ListNode));
		node->data = i;
		end->next = node;
		end = node;    //不停让他等于结尾
	}
	end->next = NULL;
	return head;
}

//判断是否为空
int ListEmpty(LinkList head)
{
	if (head->next == NULL)
		return 1;
	else
		return 0;
}

//按序号查找
ListNode *Get(LinkList L, int i)//在这里ListNode *和LinkList相同
{
	int j = 1;
	ListNode *p = L->next;
	if (i == 0)
		return L;
	if (i < 1)
		return NULL;
	while (p&&j < i)
	{
		p = p->next;
		j++;
	}
	//因为是返回链表的一个节点,所以需要获取他的地址,所以函数类型 是ListNode *类型
	return p;
}

//按内容(值)查找
LinkList *LocateElem(LinkList L, DataType e)
{
	ListNode *p = L->next;
	while (p != NULL&&p->data != e)
		p = p->next;
	//因为是返回链表的一个节点,所以需要获取他的地址,所以函数类型 是ListNode *类型
	return p;
}

//遍历链表
void TraverseList(LinkList head)
{
	LinkList p = head->next;
	if (head->next == NULL)
	{
		printf("链表为空!");
	}
	else
	{
		while (p != NULL)
		{
			printf("%d", p->data);
			p = p->next;
		}
	}
}

//插入结点
//需要调用按序号查找函数Get
//后插
LinkList Insert_back(LinkList head, DataType e, int i)
{
	LinkList m;
	//= (LinkList)malloc(sizeof(ListNode));
	//这里m的空间在Get函数里由p分配,然后把地址给m,所以m没有用到上面那行
	m=Get(head, i-1);
	LinkList s = (LinkList)malloc(sizeof(ListNode));
	s->data = e;
	s->next = m->next;
	m->next = s;
	return head;
}
//前插操作,这里的思想还是查找上方的那个结点,此改变此结点内数据实现
LinkList Insert_front(LinkList head, DataType e, int i)
{
	LinkList p;
	p = Get(head,i-1);
	LinkList s = (LinkList)malloc(sizeof(ListNode));
	s->data = e;
	s->next = p->next;
	p->next = s;
	DataType temp = p->data;
	p->data = s->data;
	s->data = temp;
	return head;
}
//前插操作其实用后插实现也可以,只需要传入i-1

//删除节点操作
//注意此删除的是链表第i个节点后的节点
void DeleteList(LinkList head, int i)
{
	LinkList p,q;
	p = Get(head, i - 1);
	q = p->next;
	p->next = q->next;
	free(q);
}

//求表长操作
int Length(LinkList head)
{
	LinkList p = head->next;
	int j=0;
	if (head->next == NULL)
	{
		printf("链表为空!");
		return 0;
	}
	else
	{
		while (p != NULL)
		{
			++j;
			p = p->next;
		}
		return j;
	}
}

//销毁链表
void Free_List(LinkList head)
{
	LinkList pointer;

	while (head != NULL)
	{
		pointer = head;
		head = head->next;
		free(pointer);
	}
}


int main()
{
	//一定记得要初始化变量
	LinkList *head = NULL, p;
	p=Creat_list1(head);
	TraverseList(p);
	//这里的head与函数参数里的head不一样,传入后修改的是函数的head
	//函数里head开辟链表头结点空间
	//若是主函数里的head开辟空间,那么即使函数用void类型,也可改变链表

	printf("\n后插\n");
	Insert_back(p,9,1);//第三个参数不能<1
	TraverseList(p);
	//p的头结点空间早已开辟好,再插入操作,即使用函数void类型,也可改变链表

	printf("\n前插\n");
	Insert_front(p, 8, 2);//第三个参数不能<2
	TraverseList(p);

	printf("\n删除节点\n");
	DeleteList(p, 1);
	TraverseList(p);

	printf("\n求表长\n");
	int length = Length(p);
	printf("length=%d\n",length);

	printf("\n销毁链表\n");
	Free_List(p);
	return 0;
}
线性表是一种常见的数据结构,它包含了一组有序的元素,元素之间具有前驱后继关系。线性表链式表示是其中一种实现方式。 线性表链式表示通过使用节点指针来表示表中元素之间的关系。具体来说,每个节点中都包含了一个元素一个指向下一个节点的指针。通过不断地遍历指针,就可以顺着链表找到表中的所有元素。 链式表示的优点是可以动态地插入删除元素,而不需要移动其他元素。这是因为链表中的节点通过指针相互连接,可以在任意位置插入删除元素。同时,链式表示可以节省内存空间,因为节点不需要连续的存储空间,可以灵活地分配内存。 实现链式表示的方式是使用结构体来定义节点指针。节点结构体中包含了一个元素一个指向下一个节点的指针。使用指针的方式可以实现链表节点之间的相互连接。 在C语言中,可以通过定义一个节点结构体表示链表的节点,然后使用指针指向链表的头节点。通过遍历指针,可以遍历整个链表,并对链表进行插入、删除等操作。 总之,线性表链式表示通过节点指针的方式来实现表中元素之间的关系。链式表示可以动态地插入删除元素,并且节省内存空间。在C语言中,可以通过定义节点结构体指针来实现链式表示,实现链表的各种操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值