c语言 单链表的增删减改

文章目录

    • 1.链表基本结构
    • 2.链表的尾插
    • 3.链表的尾删
    • 4.链表的头插与头删
      • 头插
      • 头删
    • 5.链表的查找与修改
      • 查找
      • 修改
    • 6.链表的节点插入与删除
      • 插入
      • 删除

1.链表基本结构

链表由一个个的节点连接成,这里的节点是一个结构体,由数据域与指针域组成。

typedef int SListDateType

typedef struct SListNode
{
	SListDataType data;//data变量用来存储数据
	struct SListNode* next;//next指向下一个节点;
}SListNode;
//用SListNode重新声明节点类型

不同与顺序表,链表中节点的储存不是连续的,每个节点都是分散的,通过next指针来寻找下一个节点。

链表中的尾节点的next指向NULL,并且还有一个头指针phead指向链表中第一个节点。头指针为空,说明链表是空的。

2.链表的尾插

分两种情况

1.链表为空
2.链表不为空

1.创建一个新的节点,使其指针域指向NULL,数据域放入要放的数据。最后让头指针指向该节点。
2。链表不为空时,同样也要创建一个节点。接着找到尾指针(指针域为空的节点),使其指向新的节点。

先封装创建新节点的函数

SListNode* CreatSListNode(SListDataType x)
{
	SListNode* newNode = (SListNode*)malloc(sizeof(SListNode));
	if (newNode == NULL)
	{
		printf("申请空间失败\n:);
		return 0;
	}
	else
	{
		newNode->next = NULL;
		newNode->data = x;
	}
	return newNode;
}

创建新节点并将其数据域填入数据,之后要找到尾节点(创建一个指针cur,cur最初指向首节点,如果cur的next所指向的指针不为空,cur要继续往后走,知道cur的next指向了NULL,说明cur当前指向的是尾节点),将尾节点的指针指向新节点。

当链表为空时,将头指针指向新节点,需要把头指针的值从NULL改成新节点的地址,所以这里要传址操作。

分成两种情况

void SListPushBack(SListNode** pphead,SListData x)
{
	SListNode* newNode = CreatSListNode(x);
	if (*pphead == NULL)
	{
		*phead = newNode;
		return;
	}
	else
	{
		SListNode* cur = *phead;
		while (cur->next != NULL)
			cur = cur->next;
		cur->next = newNode;
	}

3.链表的尾删

删除链表的尾节点,同样也要找到尾节点的位置,释放尾节点,将尾节点前一个节点的指针指向空。用两个指针,一个tail最后会指向尾节点,prev最后会指向尾节点前一个节点。

1.链表为空不删除
2.只有一个节点,此时删除后头指针需要指向空,因此是传址操作
3.有一个以上的节点

void SListPopBack(SListNode** pphead)
{
	if (*pphead == NULL)
		return;
	else if ((*pphead)->next == NULL)//只有一个节点
	{
		free((*pphead)->next);
		*pphead = NULL;
	}
	else
	{
		SListNode* prev = NULL;
		SListNode* tail = *pphead;
		while (tail->next)
		{
			prev = tail;
			tail = tail->next;
		}
		free(tail);
		prev->next = NULL;
	}		

4.链表的头插与头删

头插

创建新节点,将新节点的指针指向phead。

如果链表为空,指针指向phead,也就指向了NULL,此时链表有一个节点,但需要改变头指针,所以是传址操作。

如果链表有一个及以上的节点,操作与空链表时一样。

void SListPushFront(SListNode** pphead, SListDara x)
{
	SListNode* newNode = CreatSListNode(x);
	newNode->next = *pphead;
	*pphead = newNode;
}

头删

同样头删也要改变头指针,所以传址操作。将头指针实现第二个节点,释放第一个节点。

如果链表为空不删除

void SListPopFront(SListNode** pphead)
{
	if (*pphead == NULL)
		return;
	SListNode* first = *pphead;
	*pphead = (*ppehad)->next;
	free(first);
}

5.链表的查找与修改

查找

查找函数返回一个指针。指向要查找的节点,通过数据域查找节点,定义一个指针cur如果cur的data等于要查找的数据,函数返回,否则cur指向下一个节点。找不到返回NULL。

SListNode* SListNodeFind(SListNode* phead,SListData x)
{
	if (phead == NULL)
		return NULL; 
	SListNode* cur = phead;
	while (cur)
	{
		if (cur->data == x)
			return cur;
		else
			cur = cur->next;
	}
	return NULL}	

修改

查找函数返回了节点的指针,对该指针解引用就能修改里面的数据。

SListNode* pos = SListNodeFind(pList, 2);
if (pos != NULL)
	pos->data = 20;
//像这样操作

6.链表的节点插入与删除

插入

单链表的插入是将节点插入另一个节点之后。先创建一个新的节点,将该节点插入pos指针指向节点的后面,使pos指向的next指向新的节点,新节点的next指向pos之前指向的next。所以先将newNode的next指向pos的next,再将pos的next指向newNode。
viod SListInsertAfter(SListNode* pos, SListData x)
{
assert(pos);
SListNode* newNode = CreatSListNode(x);
newNode->next = pos->next;
pos->next = newNode;
}

删除

删除一个数删除的不是内存而是指向该内存的指针,也就是释放该指针。
c语言 单链表的增删减改_第1张图片
删除的是pos后面的节点,先将该节点保存为next指针,需要使pos的指针指向nextnext。

如果pos是尾节点,后面没有节点则不要删除。如果pos后面只有一个节点,删除节点后pos的指针会指向空指针,pos成为尾节点。

void SListEraseAfter(SListNode* pos)
{
	assert(pos);
	if (pos->next)
	{
		SListNode* next = pos->next;
		SListNode* nextnext = next->next;
		free(next);
		pos->next = nextnext;
	}
}

你可能感兴趣的:(【C语言】学习总结,c语言,链表,数据结构)