文章目录
- 前言
- 引入
- 1、链表定义及结构
- 链表的分类
- 3、单向不带头链表实现
- 实现
- 完整代码
- 4、带头双向循环链表实现
- 实现
- 完整代码
前言
引入
在上一篇文章中,我们认识了顺序表,但是在许多情况中,顺序表在处理一些事件时还存在许多问题,比如:
1.头插、头删或者在中部的插入或删除需要移动大量的元素,时间复杂度过高。
2.增容需要申请新空间,拷贝数据,释放旧空间,会有不小的消耗。
3.增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为50,满了以后增容到 200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了45个数据空间。
为了解决这些问题,我们提出了如下结构,链表。
1、链表定义及结构
概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
结构:列表中存在数据域与指针域,数据域用于存放该地区的值,指针域用于存放指向的下一个目标的地址。
typedef int SLTDataType;//single list
typedef struct SListNode {//数据域与指针域SLTDataType data;struct SListNode* next;
}SLTNode;
上面就是常见的单链表的结构:
1.链表在逻辑上连续,在物理上不连续
2.每一个新的区域都是动态申请出来的,申请出的区域可以连续也可以不连续
链表的分类
1.单向和双向链表
2.带头和不带头
3.循环或非循环
虽然链表的分类有很多,但在实际情况中,我们并不是都用的,比较常用的链表就是无头单向链表与带头双向循环链表。
无头单向链表
带头双向循环链表
以下,我们就来实现一下这两个链表
3、单向不带头链表实现
实现
1)结构定义:单向不带头链表分为指针域和数据域。其中指针域存放下一个位置的地址,数据域存放当前位置的值。
typedef int SLTDataType;//single list
typedef struct SListNode {//数据域与指针域SLTDataType data;struct SListNode* next;
}SLTNode;
2)尾插
//尾插
void SListPushBack(SLTNode** pphead,SLTDataType x)
{SLTNode* newNode = CreatNode(x);//指针未指向任何位置,表明链表中还没有值if (*pphead == NULL) {*pphead = newNode;}else {//新建一个临时节点,用于寻找最后一个节点SLTNode* cur = *pphead;//找最后一个节点(尾节点指向NULL位置)while (cur->next != NULL) {cur = cur->next;}//尾节点指针域存放新节点地址cur->next = newNode;}}
3)头插
//头插
void SListPushFront(SLTNode** pphead, SLTDataType x) {SLTNode* newNode = CreatNode(x);//让新节点指针域指向当前首节点newNode->next = *pphead;//新插入的节点变为了首节点*pphead = newNode;
}
4)尾删
//尾删
void SListPopBack(SLTNode** pphead) {//表里面没有值assert(*pphead);//表中只有一个值if ((*pphead)->next == NULL) {free(*pphead);*pphead = NULL;}//表中有一个或者一个以上的值else {SLTNode* cur = *pphead;SLTNode* prev = NULL;//找到尾节点和前一个节点while (cur->next != NULL) {prev = cur;cur = cur->next;}free(cur);cur = NULL;prev->next = NULL;}
}
5)头删
//头删
void SListPopFront(SLTNode** pphead) {assert(*pphead);//建立一个临时节点存储当前首节点指针域指向的地址,即第二个节点的地址SLTNode* cur = (*pphead)->next;//释放当前首节点的值free(*pphead);*pphead = NULL;//为首节点赋上第二个节点的值*pphead = cur;}
6)在位置前插入
//在pos前插入
void SListInsert(SLTNode** pphead,SLTNode* pos,SLTDataType x) {//pos位置就是首结点,就转换为头插if (pos == *pphead) {SListPushFront(pphead,x);}//pos位置是其他的节点else {SLTNode* newNode = CreatNode(x);SLTNode* prev = *pphead;while (prev->next != pos) {prev = prev->next;}//将前一个的指针域指向插入的值的地址:newNodeprev->next = newNode;//将新的值指针域指向pos位置newNode->next = pos;}}
7)在位置后插入
//在pos后插入
void SListInsertAfter(SLTNode** pphead, SLTNode* pos, SLTDataType x) {//建立一个新的节点SLTNode* newNode = CreatNode(x);//建立一个临时变量存储pos后面的节点SLTNode* after = pos->next;//让pos指向新节点pos->next = newNode;//让新节点指向刚刚pos后面的节点newNode->next = after;}
8)删除位置的值
//删除pos位置的值
void SListErase(SLTNode** pphead,SLTNode* pos) {//pos位置与首节点重合,转换为头删if (pos == *pphead) {SListPopFront(pphead);}else {SLTNode* prev = *pphead;//找pos的前一个位置while (prev->next != pos) {prev = prev->next;}//将前一个值指向pos的后一个值prev->next = pos->next;free(pos);pos = NULL;}}
9)删除位置后的值
//删除pos后面的值
void SListEraseAfter(SLTNode** pphead,SLTNode* pos) {//建立一个临时变量存储pos后两位的位置SLTNode* after = pos->next->next;free(pos->next);pos->next = NULL;//让pos指向刚刚后两位的位置pos->next = after;}
10)按值查找
//按值查找
SLTNode* SListFind(SLTNode* phead, SLTDataType x) {SLTNode* cur = phead;while (cur) {if (cur->data == x) {return cur;}cur = cur->next;}return NULL;
}
11)修改
//修改
void SListModify(SLTNode** pphead, SLTNode* pos,SLTDataType x) {pos->data = x;
}
12)保存
//保存
void SListSave(SLTNode* pphead) {FILE* pf = fopen("SListNode.txt","wb");if (pphead == NULL) {fclose(pf);pf = NULL;}else {SLTNode* cur = pphead;while (cur != NULL) {fwrite(cur,sizeof(SLTDataType),1,pf);cur = cur->next;}}}
13)打印
//打印
void SListPrint(SLTNode* phead) {SLTNode* cur = phead;if (cur == NULL) {//如果链表中无元素,则cur == NULL,不进入循环printf("NULL\n");}else {//一直遍历到最后一个位置:尾节点指向的NULL位置while (cur != NULL) {//打印数据printf("%d ", cur->data);//根据指针跳转到下一个位置cur = cur->next;}printf("\n");}
}
14)清空
//清空
void SListClear(SLTNode** pphead) {assert(*pphead);//清空链表,链表之后还要使用,所以我们只将首位置置为NULL,不释放//这里从第二个位置开始释放SLTNode* cur = (*pphead)->next;SLTNode* after = NULL;while (cur != NULL) {//先记录下一个节点的位置after = cur->next;//释放当前节点free(cur);cur = NULL;cur = after;}//清空链表,链表之后还要使用,所以我们只将首位置置为NULL,不释放*pphead = NULL;
}
15)销毁
//销毁
void SListDestroy(SLTNode** pphead) {assert(*pphead);//销毁链表,链表之后不能使用了,所以将首位置也一并释放SLTNode* cur = *pphead;SLTNode* after = NULL;while (cur != NULL) {//先记录下一个节点的位置after = cur->next;//释放当前节点free(cur);cur = NULL;cur = after;}
}
完整代码
1)SListNode.h
#pragma once#include<stdio.h>
#include<assert.h>
#include<stdlib.h>typedef int SLTDataType;//single list
typedef struct SListNode {//数据域与指针域SLTDataType data;struct SListNode* next;
}SLTNode;//打印
void SListPrint(SLTNode* phead);//头插
void SListPushFront(SLTNode** pphead, SLTDataType x);//尾插
void SListPushBack(SLTNode** pphead, SLTDataType x);//头删
void SListPopFront(SLTNode** pphead);//尾删
void SListPopBack(SLTNode** pphead);//按值查找
SLTNode* SListFind(SLTNode* phead, SLTDataType x);//在pos前插入
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);//在pos后插入
void SListInsertAfter(SLTNode** pphead, SLTNode* pos, SLTDataType x);//删除pos位置的值
void SListErase(SLTNode** pphead, SLTNode* pos);//删除pos后面的值
void SListEraseAfter(SLTNode** pphead, SLTNode* pos);//修改
void SListModify(SLTNode **pphead, SLTNode* pos, SLTDataType x);//保存
void SListSave(SLTNode* pphead);//清空
void SListClear(SLTNode** pphead);//销毁
void SListDestroy(SLTNode** pphead);
2)SListNode.c
#define _CRT_SECURE_NO_WARNINGS#include"SListNode.h"//打印
void SListPrint(SLTNode* phead) {SLTNode* cur = phead;if (cur == NULL) {//如果链表中无元素,则cur == NULL,不进入循环printf("NULL\n");}else {//一直遍历到最后一个位置:尾节点指向的NULL位置while (cur != NULL) {//打印数据printf("%d ", cur->data);//根据指针跳转到下一个位置cur = cur->next;}printf("\n");}
}//建立一个新的,可以长久储存的节点
SLTNode* CreatNode(SLTDataType x) {SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL) {perror("malloc");return NULL;}newnode->data = x;newnode->next = NULL;return newnode;
}//尾插
void SListPushBack(SLTNode** pphead,SLTDataType x)
{SLTNode* newNode = CreatNode(x);//指针未指向任何位置,表明链表中还没有值if (*pphead == NULL) {*pphead = newNode;}else {//新建一个临时节点,用于寻找最后一个节点SLTNode* cur = *pphead;//找最后一个节点(尾节点指向NULL位置)while (cur->next != NULL) {cur = cur->next;}//尾节点指针域存放新节点地址cur->next = newNode;}}//头插
void SListPushFront(SLTNode** pphead, SLTDataType x) {SLTNode* newNode = CreatNode(x);//让新节点指针域指向当前首节点newNode->next = *pphead;//新插入的节点变为了首节点*pphead = newNode;
}//头删
void SListPopFront(SLTNode** pphead) {assert(*pphead);//建立一个临时节点存储当前首节点指针域指向的地址,即第二个节点的地址SLTNode* cur = (*pphead)->next;//释放当前首节点的值free(*pphead);*pphead = NULL;//为首节点赋上第二个节点的值*pphead = cur;}//尾删
void SListPopBack(SLTNode** pphead) {//表里面没有值assert(*pphead);//表中只有一个值if ((*pphead)->next == NULL) {free(*pphead);*pphead = NULL;}//表中有一个或者一个以上的值else {SLTNode* cur = *pphead;SLTNode* prev = NULL;//找到尾节点和前一个节点while (cur->next != NULL) {prev = cur;cur = cur->next;}free(cur);cur = NULL;prev->next = NULL;}
}//按值查找
SLTNode* SListFind(SLTNode* phead, SLTDataType x) {SLTNode* cur = phead;while (cur) {if (cur->data == x) {return cur;}cur = cur->next;}return NULL;
}//在pos前插入
void SListInsert(SLTNode** pphead,SLTNode* pos,SLTDataType x) {//pos位置就是首结点,就转换为头插if (pos == *pphead) {SListPushFront(pphead,x);}//pos位置是其他的节点else {SLTNode* newNode = CreatNode(x);SLTNode* prev = *pphead;while (prev->next != pos) {prev = prev->next;}//将前一个的指针域指向插入的值的地址:newNodeprev->next = newNode;//将新的值指针域指向pos位置newNode->next = pos;}}//在pos后插入
void SListInsertAfter(SLTNode** pphead, SLTNode* pos, SLTDataType x) {//建立一个新的节点SLTNode* newNode = CreatNode(x);//建立一个临时变量存储pos后面的节点SLTNode* after = pos->next;//让pos指向新节点pos->next = newNode;//让新节点指向刚刚pos后面的节点newNode->next = after;}//删除pos位置的值
void SListErase(SLTNode** pphead,SLTNode* pos) {//pos位置与首节点重合,转换为头删if (pos == *pphead) {SListPopFront(pphead);}else {SLTNode* prev = *pphead;//找pos的前一个位置while (prev->next != pos) {prev = prev->next;}//将前一个值指向pos的后一个值prev->next = pos->next;free(pos);pos = NULL;}}//删除pos后面的值
void SListEraseAfter(SLTNode** pphead,SLTNode* pos) {//建立一个临时变量存储pos后两位的位置SLTNode* after = pos->next->next;free(pos->next);pos->next = NULL;//让pos指向刚刚后两位的位置pos->next = after;}//修改
void SListModify(SLTNode** pphead, SLTNode* pos,SLTDataType x) {pos->data = x;
}//保存
void SListSave(SLTNode* pphead) {FILE* pf = fopen("SListNode.txt","wb");if (pphead == NULL) {fclose(pf);pf = NULL;}else {SLTNode* cur = pphead;while (cur != NULL) {fwrite(cur,sizeof(SLTDataType),1,pf);cur = cur->next;}}}//清空
void SListClear(SLTNode** pphead) {assert(*pphead);//清空链表,链表之后还要使用,所以我们只将首位置置为NULL,不释放//这里从第二个位置开始释放SLTNode* cur = (*pphead)->next;SLTNode* after = NULL;while (cur != NULL) {//先记录下一个节点的位置after = cur->next;//释放当前节点free(cur);cur = NULL;cur = after;}//清空链表,链表之后还要使用,所以我们只将首位置置为NULL,不释放*pphead = NULL;
}//销毁
void SListDestroy(SLTNode** pphead) {assert(*pphead);//销毁链表,链表之后不能使用了,所以将首位置也一并释放SLTNode* cur = *pphead;SLTNode* after = NULL;while (cur != NULL) {//先记录下一个节点的位置after = cur->next;//释放当前节点free(cur);cur = NULL;cur = after;}
}
3)Test.c
#define _CRT_SECURE_NO_WARNINGS
#include"SListNode.h"void menu() {printf("*******************************\n");printf("***1、头插 2、尾插 ***\n");printf("***3、头删 4、尾删 ***\n");printf("***5、打印 6、按值查找 ***\n");printf("***7、前插 8、后插 ***\n");printf("***9、删除 10、后删 ***\n");printf("***11、修改 12、保存 ***\n");printf("***13、清空 14、销毁 ***\n");printf("***-1、退出 ***\n");printf("*******************************\n");
}enum {PushFront = 1,PushBack,PopFront,PopBack,Print,FindByValue,Insert,InsertAfter,Erase,EraseAfter,Modify,Save,Clear,Destroy,Exit = -1
};int main() {SLTNode* s = NULL;SLTDataType x;SLTNode* pos;int input = 0;do {menu();printf("请输入你想进行的操作:");scanf("%d", &input);switch (input) {case PushFront:printf("请输入你要插入的数据,以-1结束\n");do {scanf("%d", &x);if (x != -1){SListPushFront(&s,x);}} while (x != -1);break;case PushBack:printf("请输入你要插入的数据,以-1结束\n");do {scanf("%d", &x);if (x != -1){SListPushBack(&s,x);}} while (x != -1);break;case PopFront:SListPopFront(&s);break;case PopBack:SListPopBack(&s);break;case Print:SListPrint(s);break;case FindByValue:printf("请输入你想要查找的值:");scanf("%d", &x);pos = SListFind(s,x);if (pos == NULL) {printf("链表中没有这个值\n");}else {printf("找到了\n");}break;case Insert:printf("请输入你想要在哪个值前插入:");scanf("%d", &x);pos = SListFind(s,x);printf("请输入你想要插入的值:");scanf("%d", &x);if (pos == NULL) {printf("链表中没有这个值,请检查你输入的值是否正确\n");}else {SListInsert(&s, pos, x);}break;case InsertAfter:printf("请输入你想要在哪个值后插入:");scanf("%d", &x);pos = SListFind(s, x);printf("请输入你想要插入的值:");scanf("%d", &x);if (pos == NULL) {printf("链表中没有这个值,请检查你输入的值是否正确\n");}else {SListInsertAfter(&s, pos, x);}break;case Erase:printf("请输入你想要删除的值:");scanf("%d", &x);pos = SListFind(s, x);if (pos == NULL) {printf("链表中没有这个值,请检查你输入的值是否正确\n");}else {SListErase(&s, pos);}break;case EraseAfter:printf("请输入你想要删除哪个值之后的值:");scanf("%d", &x);pos = SListFind(s, x);if (pos == NULL) {printf("链表中没有这个值,请检查你输入的值是否正确\n");}else if (pos->next == NULL) {printf("这个值后已经没有值了,无法进行删除,请检查你输入的值是否正确\n");}else {SListEraseAfter(&s, pos);}break;case Modify:printf("请输入你想要修改的值:");scanf("%d", &x);pos = SListFind(s, x);printf("请输入修改后的值:");scanf("%d", &x);if (pos == NULL) {printf("链表中没有这个值,请检查你输入的值是否正确\n");}else {SListModify(&s, pos, x);}break;case Save:SListSave(s);break;case Clear:SListClear(&s);break;case Destroy:SListDestroy(&s);break;case Exit:break;default:printf("输入值错误,请重新输入\n");}} while (input != Exit);return 0;
}
4、带头双向循环链表实现
实现
1)结构定义:带头双向循环链表分为数据域、前指针域和后指针域。其中前指针域存放前一个位置的地址,后指针域存放后一个位置的地址。
typedef int LTDataType;typedef struct ListNode
{struct ListNode* next;struct ListNode* prev;LTDataType val;
}ListNode;
2)初始化头结点:创建一个头节点。前后指针域都指向自己,数据域不做处理。
//初始化创建头结点
ListNode* ListInit()
{ListNode* phead =ListCreate(0);//前指针域phead->next = phead;//后指针域phead->prev = phead;return phead;
}
3)插入
//创建新节点
ListNode* ListCreate(LTDataType x)
{//动态申请内存ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));if (newNode == NULL) {perror("malloc");}//赋值newNode->val = x;return newNode;
}//按位置插入
void ListInsert(ListNode* pos, LTDataType x){assert(pos);//建立新节点ListNode* newNode = ListCreate(x);//临时节点存储插入位置的前一个位置地址ListNode* prev = pos->prev;//将新节点后指针域存储插入位置地址newNode->next = pos;//将插入位置前指针域存储新节点位置pos->prev = newNode;//插入位置前一个位置的后指针域存储新节点位置prev->next = newNode;//将新节点前指针域存储插入位置前一个位置地址newNode->prev = prev;
}
4)删除
//按位置删除
void ListErase(ListNode* pos) {assert(pos);//创建临时节点存储插入位置前后节点地址ListNode* prev = pos->prev;ListNode* next = pos->next;//将前节点的后指针指向后节点prev->next = next;//将后节点的前指针指向前节点next->prev = prev;free(pos);pos = NULL;
}
5)头插
// 头插
void ListPushFront(ListNode* pHead, LTDataType x) {assert(pHead);ListInsert(pHead->next,x);
}
6)尾插
// 尾插
void ListPushBack(ListNode* pHead, LTDataType x) {assert(pHead);ListInsert(pHead,x);
}
7)头删
// 头删
void ListPopFront(ListNode* pHead) {assert(pHead);ListErase(pHead->next);
}
8)尾删
// 尾删
void ListPopBack(ListNode* pHead) {assert(pHead);ListErase(pHead->prev);
}
9)查找
//查找
ListNode* ListFind(ListNode* pHead, LTDataType x){assert(pHead);//新建临时节点作为首元素节点ListNode* tail = pHead->next;while (tail != pHead) {if (tail->val == x) {return tail;}tail = tail->next;}return NULL;
}
10)打印
//打印
void ListPrint(ListNode* pHead) {assert(pHead);if (pHead->next == pHead) {printf("表中无元素\n");return;}ListNode* tail = pHead->next;while (tail != pHead) {printf("%d ",tail->val);tail = tail->next;}printf("\n");
}
11)清空
//清空
void ListClear(ListNode* pHead) {assert(pHead);ListNode* tail = pHead->next;//依次对各个空间进行释放while (tail != pHead) {ListNode* next = tail->next;free(tail);tail = NULL;tail = next;}//修改头结点前后指针域pHead->next = tail;pHead->prev = tail;
}
12)销毁
//销毁
void ListDestory(ListNode* pHead) {assert(pHead);ListNode* tail = pHead->next;//依次对各个空间进行释放while (tail != pHead) {ListNode* next = tail->next;free(tail);tail = NULL;tail = next;}//释放头结点free(pHead);pHead = NULL;
}
完整代码
1)ListNode.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int LTDataType;typedef struct ListNode
{struct ListNode* next;struct ListNode* prev;LTDataType val;
}ListNode;// 创建返回链表的头结点.
ListNode* ListInit();
// 双向链表销毁
void ListDestory(ListNode* pHead);
// 双向链表打印
void ListPrint(ListNode* pHead);
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* pHead);
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x);
// 双向链表头删
void ListPopFront(ListNode* pHead);
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);
//清空
void ListClear(ListNode* pHead);
//打印
void ListPrint(ListNode* pHead);
2)ListNode.c
#define _CRT_SECURE_NO_WARNINGS#include"ListNode.h"//创建新节点
ListNode* ListCreate(LTDataType x)
{//动态申请内存ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));if (newNode == NULL) {perror("malloc");}//赋值newNode->val = x;return newNode;
}//初始化创建头结点
ListNode* ListInit()
{ListNode* phead =ListCreate(0);//前指针域phead->next = phead;//后指针域phead->prev = phead;return phead;
}//查找
ListNode* ListFind(ListNode* pHead, LTDataType x){assert(pHead);//新建临时节点作为首元素节点ListNode* tail = pHead->next;while (tail != pHead) {if (tail->val == x) {return tail;}tail = tail->next;}return NULL;
}//按位置插入
void ListInsert(ListNode* pos, LTDataType x){assert(pos);//建立新节点ListNode* newNode = ListCreate(x);//临时节点存储插入位置的前一个位置地址ListNode* prev = pos->prev;//将新节点后指针域存储插入位置地址newNode->next = pos;//将插入位置前指针域存储新节点位置pos->prev = newNode;//插入位置前一个位置的后指针域存储新节点位置prev->next = newNode;//将新节点前指针域存储插入位置前一个位置地址newNode->prev = prev;
}//按位置删除
void ListErase(ListNode* pos) {assert(pos);//创建临时节点存储插入位置前后节点地址ListNode* prev = pos->prev;ListNode* next = pos->next;//将前节点的后指针指向后节点prev->next = next;//将后节点的前指针指向前节点next->prev = prev;free(pos);pos = NULL;
}//打印
void ListPrint(ListNode* pHead) {assert(pHead);if (pHead->next == pHead) {printf("表中无元素\n");return;}ListNode* tail = pHead->next;while (tail != pHead) {printf("%d ",tail->val);tail = tail->next;}printf("\n");
}//清空
void ListClear(ListNode* pHead) {assert(pHead);ListNode* tail = pHead->next;//依次对各个空间进行释放while (tail != pHead) {ListNode* next = tail->next;free(tail);tail = NULL;tail = next;}//修改头结点前后指针域pHead->next = tail;pHead->prev = tail;
}//销毁
void ListDestory(ListNode* pHead) {assert(pHead);ListNode* tail = pHead->next;//依次对各个空间进行释放while (tail != pHead) {ListNode* next = tail->next;free(tail);tail = NULL;tail = next;}//释放头结点free(pHead);pHead = NULL;
}// 尾插
void ListPushBack(ListNode* pHead, LTDataType x) {assert(pHead);ListInsert(pHead,x);
}
// 尾删
void ListPopBack(ListNode* pHead) {assert(pHead);ListErase(pHead->prev);
}
// 头插
void ListPushFront(ListNode* pHead, LTDataType x) {assert(pHead);ListInsert(pHead->next,x);
}
// 头删
void ListPopFront(ListNode* pHead) {assert(pHead);ListErase(pHead->next);
}
3)Test.c
#define _CRT_SECURE_NO_WARNINGS#include"ListNode.h"void TestList1()
{ListNode* plist = ListInit();ListPushBack(plist, 1);ListPushBack(plist, 2);ListPushBack(plist, 3);ListPushBack(plist, 4);ListPrint(plist);ListPushFront(plist, 0);ListPushFront(plist, -1);ListPrint(plist);ListPopFront(plist);ListPopFront(plist);ListPopFront(plist);ListPrint(plist);ListPopBack(plist);ListPrint(plist);ListNode* pos = ListFind(plist, 3);if (pos){// 查找,附带着修改的作用pos->val *= 10;printf("找到了,并且节点的值乘以10\n");}else{printf("没有找到\n");}ListPrint(plist);ListInsert(pos, 300);ListPrint(plist);ListErase(pos);ListPrint(plist);ListClear(plist);ListPrint(plist);ListDestory(plist);
}int main() {TestList1();return 0;
}