详解C++中链表的基本操作
利用链表操作实现的链表数据管理系统:
#include<iostream> #include "myfun.h" using namespace std; enum Status{ OK = true, ERROR = false }; typedef struct LNode{ int data; LNode* next; }L,*LinkList; Status Print_LS(LinkList L); Status Create_LS(LinkList L,const int N); void Init_L(LinkList L); Status Insert_LS(LinkList& L,const int i); Status Delete_LS(LinkList& L,const int i); Status Search_LS(LinkList L,const int data,int& e); Status Change_LS(LinkList& L,const int data1,const int data2); int main(void){ cout << "程序规则如下:" << endl; cout << "1.链表值为1~100之间的随机数" << endl; cout << "2.输入show:则输出链表" << endl; cout << "3.输入insert i:则在i下标后插入一个随机数" << endl; cout << "4.输入delete i:则删除第i个元素(注意不是下标)" << endl; cout << "5.输入search n:则输出n在链表中的下标" << endl; cout << "6.输入change m n:则将链表中的元素m改为n" << endl; srand(time(0)); LinkList L = new LNode; Init_L(L); Create_LS(L,9); //在初始节点后面插入 9 个节点 Print_LS(L); string str; cout << "请输入操作指令:"; while (cin >> str){ if (str == "show"){ Print_LS(L); cout << "********************" << endl; } else if (str == "insert"){ int i;cin >> i; if (Insert_LS(L,i)){ cout << "insert OK" << endl; cout << "********************" << endl; } else{ cout << "insert fail!" << endl; cout << "********************" << endl; } } else if (str == "delete"){ int i;cin >> i; if (Delete_LS(L,i)){ cout << "delete OK" << endl; } else{ cout << "delete fail!" << endl; } } else if (str == "search"){ int data,e; cin >> data; if (Search_LS(L,data,e)){ cout << "search OK!\nThe Index: " << e << endl; } else{ cout << "search fail!" << endl; } cout << "********************" << endl; } else if (str == "change"){ int data1,data2; cin >> data1 >> data2; if (Change_LS(L,data1,data2)){ cout << "change OK" << endl; } else { cout << "change fail!" << endl; } cout << "********************" << endl; } cout << "请输入操作指令:"; } return 1; }; void Init_L(LinkList L){ L->data = randint(1,100); L->next = NULL; } Status Print_LS(LinkList L){ LinkList p = L; int i = 0; cout << "元素:"; while (p){ i++; printf("%-3d",p->data); p = p->next; } cout << endl; cout << "索引:"; for (int j=0;j<i;j++){ printf("%-3d",j); } cout << endl; cout << "序号:"; for (int j=0;j<i;j++){ printf("%-3d",j+1); } cout << endl; return OK; } Status Search_LS(LinkList L,const int data,int& e){ //寻找第一个出现data的下标 int i = 0; LinkList cur = L; while (cur){ if (cur->data == data){ break; } i++; cur = cur->next; } if (!cur){ return ERROR; } e = i; return OK; } Status Create_LS(LinkList L,const int N){ LinkList p,cur; p = L; cur = L; cout << "随机生成链表成功!" << endl; for (int i=0;i<N;i++){ p = new LNode; p->data = randint(1,100); cur->next = p; cur = p; } if (cur == NULL){ return ERROR; } p->next = NULL; return OK; } Status Insert_LS(LinkList& L,const int i){ int j = 0; LinkList cur = L; if (i < 1){ LinkList newL = new LNode; Init_L(newL); newL->next = L; L = newL; return OK; } while (j < i-1 && cur->next){ cur = cur->next; j++; } LinkList newL = new LNode; Init_L(newL); newL->next = cur->next; cur->next = newL; return OK; } Status Delete_LS(LinkList& L,const int i){ int j = 0; LinkList cur = L; if (i < 1){ return ERROR; } else if(i == 1){ L = cur->next; delete cur; return OK; } while (j < i-2){ if (!(cur->next->next)){ //一个神奇的判断越界魔法代码<( ̄︶ ̄)↗ return ERROR; } cur = cur->next; j++; } LinkList delCur = cur->next; cur->next = delCur->next; delete delCur; return OK; } Status Change_LS(LinkList& L,const int data1,const int data2){ LinkList cur = L; while (cur){ if (cur->data == data1){ cur->data = data2; //改 return OK; } } return ERROR; }
myfun.h头文件往下翻 👇👇👇
以上为项目完整代码,是不是很简单呢?(doge)🐕🐕🐕
★★★★★★下面进行解析:
★☆☆☆☆☆一、链表的创建
初始化代码省略.
Status Create_LS(LinkList L,const int N){ LinkList p,cur; //用双指针进行动态分配 cur = L; cout << "随机生成链表成功!" << endl; for (int i=0;i<N;i++){ p = new LNode; //用p创建一个新的指针 p->data = randint(1,100); //初始化新节点的值[1,100] cur->next = p; //让链表最后一个节点指向新的节点 cur = p; //更新链表最后一个节点 } if (cur == NULL){ //这段代码没用可以不写 return ERROR; } p->next = NULL; //最后一个节点指向空代表结束 return OK; }
☆★☆☆☆☆二、链表的打印
Status Print_LS(LinkList L){ LinkList p = L; int i = 0; //累加器用于求链表中元素数量 cout << "元素:"; while (p){ //只要指针不为空就打印 i++; printf("%-3d",p->data); p = p->next; //指针指向下一个链表节点 } cout << endl; cout << "索引:"; //格式化输出打印索引 for (int j=0;j<i;j++){ printf("%-3d",j); } cout << endl; cout << "序号:"; //格式化输出打印序号 for (int j=0;j<i;j++){ printf("%-3d",j+1); } cout << endl; return OK; //返回状态(成功) }
☆☆★☆☆☆三、链表的查找
Status Search_LS(LinkList L,const int data,int& e){ //寻找第一个出现data的下标 int i = 0; //i先记录为元素索引 LinkList cur = L; //指针指向头节点 while (cur){ if (cur->data == data){ //只要找到要查找的元素就退出循环 break; } i++; //没有找到下标增加 cur = cur->next; //指针指向下一个节点元素 } if (!cur){ return ERROR; //如果找了一圈指针最后指向空说明没有找到 } //所以返回错误 e = i; return OK; //没有错误就是成功咯~ }
不难看出,i 的下标和 cur 所指向的节点是同步增加的,即 i 就是 cur 所指向节点的下标
☆☆☆★☆☆四、链表的插入
Status Insert_LS(LinkList& L,const int i){ //在链表的第 i 个位置后插入新的节点 int j = 0; //j开始时指向第一个节点的下标索引 LinkList cur = L; //cur指向第一个节点 if (i < 1){ //如果要插入的节点在头节点的前面则单独处理 LinkList newL = new LNode; //在内存中分配一个新的节点用newL指向它 Init_L(newL); //初始化新节点的数据 newL->next = L; //头插法:新节点指向我们的头节点 L = newL; //别忘记更改头节点,传入L指针的引用的作用 return OK; //返回修改成功 } while (j < i-1 && cur->next){ //不需要头插的情况,如果cur下一个节点为空(说明给的下标超过长 //度了,但是我们照样插入到最后面 cur = cur->next; //指针指向下一个节点 j++; //j索引往后移动 } //循环结束cur指向需要插入的节点位置 LinkList newL = new LNode; //新建一个孤儿节点(因为此时它和链表无关) Init_L(newL); //初始化节点数据 newL->next = cur->next; //新的节点指向我们要插入的节点的下一个节点 cur->next = newL; //再让我们的节点指向新的节点,完成插入! return OK; //返回插入成功的状态->true }
Tips:插入的时候要注意两种情况:
1.插在头节点前,则要更新我们的头节点,这里参数传入的是指针的引用就是为了这一步,否则函数会生成一个指针的副本,对指针进行的修改会失效(函数种传入指针只能够修改指针所指的地址的数据,而指针本身和传入普通变量一样都是副本)。
2.插入的位置超出我们的链表长度了,那么这时我们使用(cur->next)传入判断,如果为下一个是空节点就不继续往下走了,然后我们的指针会留在最后一个节点,直接插就完事了。
注意:这里实际上可以单独判断,然后返回ERROR来报错,但是我就不这么做了。
☆☆☆☆★☆五、链表的删除
Status Delete_LS(LinkList& L,const int i){ int j = 0; //老样子,j为第一个节点的下标 LinkList cur = L; //老样子,链表指针指向第一个节点 if (i < 1){ return ERROR; //如果删除的位置非法,即<=0,返回错误 } else if(i == 1){ //如果删除的是头节点 L = cur->next; //头节点往后移动一下就行 delete cur; //同时也别忘记释放被删除的节点内存 return OK; //返回删除成功 } while (j < i-2){ //i-1是要删除节点的下标,i-2为删除节点前节点 if (!(cur->next->next)){ //一个神奇的判断越界魔法代码<( ̄︶ ̄)↗ return ERROR; //在纸上画出整个链表演算一遍你就明白了!! } cur = cur->next; //指针后移 j++; //索引同步后移 } LinkList delCur = cur->next; //循环结束后cur的位置是删除节点的前节点 //delCur就是cur的下一个节点 cur->next = delCur->next; //让被删的前节点指向它的下一个节点 delete delCur; //释放被删节点分配的内存 return OK; //返回成功 }
链表的删除就是,让被删的节点的前节点指向其下一个节点,从而让它从链表中剔除。
☆☆☆☆☆★六、链表的修改
Status Change_LS(LinkList& L,const int data1,const int data2){ LinkList cur = L; //初始化cur,指向头节点 while (cur){ //如果cur指针不为空 if (cur->data == data1){ //如果节点数据等于需要改的元素 cur->data = data2; //修改链表元素 return OK; //返回成功并结束函数 } } //结束循环,cur指向NULL说明没找到 return ERROR; //返回查找失败 }
其他定义与函数:
enum Status{ //枚举型定义状态 OK = true, //注意bool类型属于C++,C中可以用1/0来替代 ERROR = false }; typedef struct LNode{ //链表节点的定义 int data; LNode* next; }L,*LinkList; //给指针型和节点型各起一个别名用来使用 void Init_L(LinkList L){ //给一个节点进行初始化 L->data = randint(1,100); L->next = NULL; }
myfun.h头文件的代码:
#include<stdlib.h> //stdlib.h用来使用rand()生成随机数 #include<ctime> //时间库,用来在主函数中生成时间种子 #include<iostream> int randint(int a,int b){ //相当于Python中random库中的randint(a,b) return rand()%(b-a+1)+a; //返回一个在[a,b]范围内的整数 }
main函数主体:
int main(void){ //程序开始时输出提示 cout << "程序规则如下:" << endl; cout << "1.链表值为1~100之间的随机数" << endl; cout << "2.输入show:则输出链表" << endl; cout << "3.输入insert i:则在i下标后插入一个随机数" << endl; cout << "4.输入delete i:则删除第i个元素(注意不是下标)" << endl; cout << "5.输入search n:则输出n在链表中的下标" << endl; cout << "6.输入change m n:则将链表中的元素m改为n" << endl; /***生成一个时间种子来达到伪随机的效果***/ srand(time(0)); LinkList L = new LNode; //为链表第一个数据分配空间 Init_L(L); //初始化链表 Create_LS(L,9); //在初始节点后面插入 9 个随机生成值的节点 Print_LS(L); //先打印一遍我们随机生成的链表看看 string str; //字符类存放输入的指令 cout << "请输入操作指令:"; while (cin >> str){ //一直输入除非EOF if (str == "show"){ //根据输入的指令选择操作 Print_LS(L); cout << "********************" << endl; } else if (str == "insert"){ int i;cin >> i; if (Insert_LS(L,i)){ cout << "insert OK" << endl; cout << "********************" << endl; } else{ cout << "insert fail!" << endl; cout << "********************" << endl; } } else if (str == "delete"){ int i;cin >> i; if (Delete_LS(L,i)){ cout << "delete OK" << endl; } else{ cout << "delete fail!" << endl; } } else if (str == "search"){ int data,e; cin >> data; if (Search_LS(L,data,e)){ cout << "search OK!\nThe Index: " << e << endl; } else{ cout << "search fail!" << endl; } cout << "********************" << endl; } else if (str == "change"){ int data1,data2; cin >> data1 >> data2; if (Change_LS(L,data1,data2)){ cout << "change OK" << endl; } else { cout << "change fail!" << endl; } cout << "********************" << endl; } cout << "请输入操作指令:"; } return 1; };
以上就是C++中链表操作的基本内容了,实际上也
可以用面向对象来实现,但是一般选择结构体来实现较为便捷高效。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」