Study

本文详细介绍了C语言中单链表的基本概念、定义及操作方法。包括链表的打印、插入、删除等功能的实现代码,帮助读者快速掌握单链表的使用。

c语言单链表学习小结

1.链表的概念:物理存储结构上非连续、非顺序的存储结构,链表的顺序逻辑是依照链表中的指针链接次序来实现的。
1.2优点:可以更合理地使用空间,而且在进行数据的插入时,不需要对整个链表的数据进行移动。
1.3缺点:无法进行随机访问,即以下标来访问数据。每一个节点还需要额外存储指向下一个节点的指针。
2.单链表定义:

typedef int SLNodeDataType;//第一行将int重定义为SLNodeDataType类型,是为了方便更改链表存储的类型。
typedef struct SingleListNode
{
	SLNodeDataType data;
	struct SingleListNode* next;
} SLNode;//这里定义了一个结构体,储存的数据是int类型的data,以及指向下一节点的指针next。并重命名为SLNode,方便调用。

解释:
3.单链表的使用
3.1单链表的打印
打印函数:

void SLNodePrint (SLNode* phead) //以结构体指针pHead来当作形参。
{
	SLNode* cur = pHead; //构建结构体指针cur来指代pHead,防止对原链表的更改。
	while(cur->next != NULL//当cur中的next指针指向为NULL时,表明此时的cur已经是尾结点了,即打印完毕。
	{
		printf("%d->",cur->data) //打印cur当中的数据data。
		cur = cur->next; //跳出循环的语句,也是遍历的语句。
	}
	printf("NULL\n"); //尾结点指向NULL。
}

3.2单链表插入数据
思路:要在链表中插入数据,就得新建一个节点,然后让上一节点的next指向这个新节点,而这个新节点的next指向应指向的下一节点。尾插情况下,新节点的next指向NULL。
新建结点函数:

SLNode* CreatNewNode(SLNodeDataType x)
{
	SLNode* new_node = (SLNode*)malloc(sizeof(SLNode)); //定义一个新的结构体指针变量,并用malloc函数开辟一个SLNode*类型,大小为SLNode大小的节点。
	if (new_node == NULL) //判断动态开辟空间有没有成功。
	{
		printf("malloc failed\n");
		exit(-1);
	}
	new_node->data = x; //输入data数据。
	new_node->next = NULL; //及时将指针置空,防止野指针访问。

	return new_node; //返回new_node,因而函数的返回值类型为SLNode*
}

插入数据的情况:尾插,头插,中间节点插入。
尾插需要找到尾节点,然后尾节点的next指针指向新节点即可。头插更简单,新节点的next指针指向之前的头节点,然后给头节点赋值new_node。

void SLNodePushBack(SLNode** ppHead,SLNodeDataType x) //尾插函数,因为要传入的参数就是一个指针,所以要用二级指针来接收。
{
	SLNode* new_node = CreatNewNode(x);
	if (*ppHead == NULL)
	{
		*ppHead = new_node;
	}
	else
	{
		SLNode* cur = *ppHead;
		while (cur->next != NULL)
		{
			cur = cur->next;
		}
		cur->next = new_node;
	}
}
void SLNodePushFront(SLNode** ppHead,SLNodeDataType x)
{
	SLNode* new_node = CreatNewNode(x);
	new_node->next = *ppHead;
	*ppHead = new_node;
}

链表中段插入又分为目标节点插入或者是目标节点后插入。

void SLNodePushInsert(SLNode** ppHead,SLNode* pos,SLNodeDataType x)
{
	if (pos == *ppHead)//如果pos为头节点,直接调用头插函数
	{	
		SLNodePushFront(ppHead,x)
	}
	else
	{
		SLNode* new_node = CreatNewNode(x);
		SLNode* cur = *ppHead;//创建一个临时的cur变量,来找到pos节点的前一个节点。
		while (cur->next != pos)
		{
			cur = cur->next;
		}
		cur->next = new_node;
		new_node->next = pos;
	}
}		
void SLNodeAfterInster(SLNode** ppHead,SLNode* pos,SLNodeDataType x)
{
	assert(pos);//防止没有节点
	SLNode* new_node = CreatNewNode(x);
	SLNode* cur = pos->next;
	pos->next = new_node;
	new_node->next = cur;
}
		

3.3单链表的数据删除
思路:尾部的数据删除直接将原尾节点free掉,然后前一节点的next指针置空。头部的数据删除,直接将原头节点free,然后后*ppHead赋值为下一节点。中间节点的删除,先将前一节点的next指针指向pos节点的下一节点,然后free(pos)。

void SLNodePopBack(SLNode** ppHead)
{
	assert(*ppHead != NULL);//防止对空链表进行删除。
	
	if (*ppHead->next == NULL)//如果链表只有一个头节点。
	{
		free(*ppHead);
		*ppHead = NULL;
	}
	else
	{
		SLNode* pre = NULL; //前驱指针变量,为了将新的尾节点中的next指针置空。
		SLNode* cur = *ppHead; //寻尾指针变量。
		while (cur->next != NULL)
		{
			pre = cur;
			cur = cur->next;
		}
	free(cur);
	cur = NULL;
	pre->next = NULL;
	}
}	
void SLNodePopFront(SLNode** ppHead)
{
	assert(*ppHead != NULL)

	SLNode* cur = (*ppHead)->next;//定义cur指针变量,使其为头节点的下一节点,无则为NULL。
	free(*ppHead);
	*ppHead = cur;
}
void SLNodeEarse(SLNode** ppHead,SLNode* pos)
{
	assert(*ppHead);
	assert(pos);

	if (*ppHead == pos)
	{
		SLNodePopFront(pos);
	}
	else
	{
		SLNode* cur = *ppHead;
		while (cur->next != pos)
		{
			cur = cur->next;
		}
	cur->next = pos->next;
	free(pos);
	pos = NULL;
}
void SLNodeAfterEarse(SLNode* pos)
{
    assert(pos);
    assert(pos->next);

    SLNode* cur = pos->next;
    pos->next = cur->next;
    free(cur);
    cur = NULL;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值