目录
前言
01销毁链表
02 清空链表
测试代码
前言
🎬 个人主页:@ChenPi
🐻推荐专栏1: 《C++_@ChenPi的博客-CSDN博客》✨✨✨
🔥 推荐专栏2: 《Linux C应用编程(概念类)_@ChenPi的博客-CSDN博客》✨✨✨
📝推荐专栏3: 《 链表_@ChenPi的博客-CSDN博客》 ✨✨✨
🍉本篇简介 : 链表清空链表|销毁链表
✨ 只有我努力了 才有机会接触成功✨
链表是一种常见的基础数据结构,结构体指针在这里得到了充分的利用。链表可以动态的进行存储分配,也就是说,链表是一个功能极为强大的数组,他可以在节点中定义多种数据类型,还可以根据需要随意增添,删除,插入节点。链表都有一个头指针,一般以head来表示,存放的是一个地址。链表中的节点分为两类,头结点和一般节点,头结点是没有数据域的。链表中每个节点都分为两部分,一个数据域,一个是指针域。说到这里你应该就明白了,链表就如同车链子一样,head指向第一个元素:第一个元素又指向第二个元素;……,直到最后一个元素,该元素不再指向其它元素,它称为“表尾”,它的地址部分放一个“NULL”(表示“空地址”),链表到此结束。
作为有强大功能的链表,对他的操作当然有许多,比如:
- 链表的创建
- 链表的链表的遍历打印数据
- 链表里面的结构体数据的修改
- 链表节点的删除
- 链表插入新节点
- 链表的数据排序
- 链表的反序
- 清空链表的元素
- 求链表的长度等
在前面几章,我们学习了
- 链表的创建
- 链表的链表的遍历打印数据
- 链表里面的结构体数据的修改
- 求链表的长度等
- 还有链表结尾插入数据节点,非指定节点
- 链表指定节点后方插入数据
- 链表头的前方插入数据
- 删除链表节点
今天我们学清空链表和销毁链表
单链表的销毁与清空
- 销毁:连同头结点一起释放
- 清空:保留头结点;置头结点的指针域为NULL
01销毁链表
销毁链表就是将链表在堆中构造的节点全部销毁,反正内存泄漏
我们首先 要定义一个函数destroyList,然后又一个参数,参数为一个结构体指针,用于传入链表的头节点,然后返回值也是一个结构体指针,不过链表销毁后,链表的头节点也就是个空指针了
销毁链表的函数大致就是长这样了
编译测试一下,我们先将链表清空在拿去打印试一下
没有问题,链表已经被清空了,链表的头指向了NULL
02 清空链表
链表的清空就是保留头结点,然后让他节点的next = NULL就可以,代码上如上,但是有一点,链表是清空了,但是节点的内存是否完全释放,这个我确实不清楚了,不过我debug查看内存的时候,p最后的指向是指向NULL,最后释放
这里我不是特别懂,如果有大佬会的话可以个我将一下,谢谢
编译测试一下,没有问题,链表是被清剩下一个头节点了
测试代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>struct Link
{int data;struct Link *next;
};/*打印链表数据*/
void PrintLink(struct Link *head)
{if(NULL == head){puts("ERROR 空链表");return;}struct Link *prev = head;while (NULL != prev) {printf("%d ", prev->data);prev = prev->next;}printf("\n");
}/*获取链表的节点数*/
int GetLinkNum(struct Link *head)
{struct Link *prev = head;int count = 0;while (prev != NULL){count++;prev = prev->next;}return count;
}struct Link *getHead(int data)
{struct Link* head = (struct Link*)malloc(sizeof(struct Link));head->data = data;head->next = NULL;return head;
}/* 链表头插入数据,不指定位置*/
struct Link* frontInsertDataLink(struct Link *head, int data)
{struct Link *prev = head;struct Link *newLink = (struct Link *)malloc(sizeof(struct Link));newLink->data = data;newLink->next = prev;return newLink;
}struct Link *frontInsertNodeDataLink(struct Link *head,int NodeIndex,int data)
{struct Link *prev = head;int cnt = 1;if(NodeIndex > GetLinkNum(prev)||(NodeIndex<0)){printf("ERROR: Link index out of range");return NULL;}else if (NodeIndex == 1){prev = frontInsertDataLink(prev,data);return prev;}while (NULL != prev->next){if(cnt == NodeIndex-1){struct Link *newLink = (struct Link *)malloc(sizeof(struct Link));newLink->data = data;newLink->next = prev->next;prev->next = newLink;return head;}cnt++;prev = prev->next;}return NULL;
}struct Link * deleteHeadLinkNode(struct Link *head,int NodeIndex)
{struct Link *prev = head; //保存头节点的地址int cnt = 1;if(NodeIndex > GetLinkNum(prev)||(NodeIndex<0)) //判断是否越界{printf("ERROR: Link index out of range");return NULL;}if(1 == NodeIndex) //如果要删除头节点{head = head->next;free(prev);return head;}struct Link *prior = NULL; //遍历时用来保留前一个节点的状态while (NULL != prev) //判断是不是最后一个节点{prior = prev;//用来保留前一个节点的状态prev = prev->next; //走向下一个节点,也就是循环增量if(cnt == NodeIndex-1) //找到需要删除的节点{if(NULL == prev->next) //1.如果找到的是尾节点{prior->next = NULL; //原来尾节点的前一个为节点变成了新尾节点free(prev); //释放原来尾节点的内存return head;}else //如果找到的是普通节点{prior->next = prev->next; //要删除的节点的前一个节点和后一个节点相连free(prev);return head;}}cnt++;}return NULL; //没找到对应节点,操作失败,返回NULL
}//销毁链表
struct Link* destroyList(struct Link *head)
{struct Link *p = head;while (p != NULL){head = head->next;free(p);p = head;}return head;
}//清空链表
void clearList(struct Link *head)
{struct Link *p;while (head->next) {p = head->next;head->next = p->next;free(p);}p = NULL;free(p);
}int main()
{struct Link *head = getHead(3);head = frontInsertDataLink(head, 5); head = frontInsertDataLink(head, 2); PrintLink(head);head = frontInsertNodeDataLink(head, 1,4);PrintLink(head);head = deleteHeadLinkNode(head,2);PrintLink(head);head = destroyList(head);//head = destroyList(head);PrintLink(head);return 0;
}