详解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++中链表操作的基本内容了,实际上也可以面向对象来实现,

但是一般选择结构体来实现较为便捷高效。

posted @   IoOozZzz  阅读(108)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示