主要写给自己看,欢迎指错,看了四五天才看出点头绪。很菜!
为什么要使用链表?
在知乎看到了一个比较好的例子:
举个生活中的例子,你上学的时候要站队升国旗,一列纵队,一人一个按顺序从0开始的编号。这就是数组。万一有一天,你们来了一个插班生,要站在队伍中间,那么他后面的人就要重新编号(全都+1),这就比较麻烦了因为要重新编号,最坏情况是所有都要重编。
但是我们如果试着用另外一种方式去记录位置,每个人只要记住他后面那个人的名字。那么每一次站队的时候,只要知道队首那个人,然后队首的小明一喊,我后面的是小黄,然后小黄就过来,小黄知道后面的是小黑,然后小黑就过来,直到所有人都找好位置。如果有一个人,小白插进来,比如小黄和小黑之间,我们只要和小黄说,你后面现在要改成小白,小白你后面是小黑。这样只要两个步骤就可以了。
总的来说,有些操作在数组中操作比较麻烦,而链表则可以方便的执行
下面,分步实现比较好理解(受知乎某答主启发)
①定义链表单个节点的数据结构
#include <iostream>
struct student
{
int score;
student *next;
};
int main()
{
student p;
p.score=60;
}
②用指针实现
#include <iostream>
struct student
{
int score;
student *next;
};
int main()
{
student *p;
p->score=60;
}
③使用指针前动态分配空间
#include <iostream>
#include <malloc.h>
struct student
{
int score;
student *next;
};
int main()
{
student *p;
p=(student*)malloc(sizeof(student));//需要头文件
p->score=60;
}
④实现两个节点的串联(链表本就是佛珠一样的,一个连着一个)
#include <iostream>
#include <malloc.h>
struct student
{
int score;
student *next;
};
int main()
{
student *p1,*p2;
p1=(student*)malloc(sizeof(student));//需要头文件
p1->score=60;
p2=(student*)malloc(sizeof(student));
p2->score=70;
p1->next=p2;//第一个节点指向第二个
}
⑤增加链表最后一个节点的结束标志(NULL)
#include <iostream>
#include <malloc.h>
struct student
{
int score;
student *next;
};
int main()
{
student *p1,*p2;
p1=(student*)malloc(sizeof(student));//需要头文件
p1->score=60;
p2=(student*)malloc(sizeof(student));
p2->score=70;
p1->next=p2;//第一个节点指向第二个节点
p2->next=NULL;//在p2时指向NULL(空/0)结束
}
⑥ 添加头指针
#include <iostream>
#include <malloc.h>
struct student
{
int score;
student *next;
};
int main()
{
student *head; //添加头指针
student *p1,*p2;
p1=(student*)malloc(sizeof(student));//需要头文件
p1->score=60;
p2=(student*)malloc(sizeof(student));
p2->score=70;
p1->next=p2;//第一个节点指向第二个节点
p2->next=NULL;//在p2时指向NULL(空/0)结束
head=p1;//指向第一个节点
}
⑦利用循环进行n个节点的信息存储
#include <iostream>
#include <malloc.h>
using namespace std;
struct student
{
int score;
student *next;
};
int main()
{
student *head;
student *p1,*p2;
int n;
cin>>n;
head=NULL;
for(int i=0;i<n;i++)
{
p1=(student*)malloc(sizeof(student));//执行一次开一个动态空间
cin>>p1->score;//存储信息
if(head==NULL)//判断是否为空链表
{
head=p1;
p2=p1;
}
else//循环指向,个人认为较难理解
{
p2->next=p1;
p2=p1;
}
}
p2->next=NULL;//结束
}
⑧存储之后,当然是输出了
#include <iostream>
#include <malloc.h>
using namespace std;
struct student
{
int score;
student *next;
};
int main()
{
student *head;
student *p1,*p2;
int n;
cin>>n;
head=NULL;
for(int i=0;i<n;i++)
{
p1=(student*)malloc(sizeof(student));
cin>>p1->score;
if(head==NULL)
{
head=p1;
p2=p1;
}
else
{
p2->next=p1;
p2=p1;
}
}
p2->next=0;
//下面为输出代码
student *p;
p=head;
while(p!=NULL)
{
cout<<p->score<<endl;
p=p->next;
}
}
⑨然后是链表节点的删除
#include <iostream>
#include <malloc.h>
using namespace std;
struct student
{
int score;
student *next;
};
int main()
{
student *head;
student *p1,*p2;
int n;
cin>>n;
head=NULL;
for(int i=0;i<n;i++)
{
p1=(student*)malloc(sizeof(student));
cin>>p1->score;
if(head==NULL)
{
head=p1;
p2=p1;
}
else
{
p2->next=p1;
p2=p1;
}
}
p2->next=0;
//节点删除代码
p1=head;
while(p1->score!=60)//删除score为60的节点,当然这里与上面的存储有关,视情况更改数据即可
{
p2=p1;
p1=p1->next;
}
p2->next=p1->next;
delete p1;
//下面为输出代码
student *p;
p=head;
while(p!=NULL)
{
cout<<p->score<<endl;
p=p->next;
}
}
⑩ 其他的还有插入节点,新增节点等功能,暂时不会。。。。
下面附一段较为完整的代码,此代码转自他人!!!!!(纯手打!)
//
//实现链表的基本操作
//
#include <stdio.h>
#include <malloc.h>
struct node//链表上的数据结构
{
int data;
node *next;
};
node *Create(void)//产生一条无序链表
{
node *p1,*p2,*head;//p2指向最后一个节点,p1指向插入节点 ,head指向头节点、
int a;
head=0;
printf("产生一条无序链表,请输入数据,以-1结束:\n");
scanf("%d",&a);
while(a!=-1)//1,3,2,4,-1
{
p1=(node*)malloc(sizeof(node));
p1->data=a;
if(head==0)//插入链表首部
{
head=p1;
p2=p1;
}
else// 插入表尾
{
p2->next=p1;
p2=p1;
}
scanf("%d",&a);
}
if(head)
{
p2->next=0;
}
return (head);
}
void Print(node *head)//输出各节点数据
{
node *p;
p=head;
printf("链表上各节点的数据为:\n");
while(p!=0)
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
node *Delete_one_node(node *head,int num)//根据数值删除对应节点
{
node *p1,*p2;
if(head==0)
{
printf("链表为空,无节点可删除!\n");
return 0;
}
if(head->data==num)//删去首节点
{
p1=head;
head=head->next;
free((void*)p2);//释放节点空间
printf("删除了一个节点!\n");
}
else
{
printf("未找到要删除的节点!\n");
}
return head;
}
node *Insert(node *head,node *p)//将一个节点插入链表中
{
node *p1,*p2;
if(head==0)//空链表,插入链表首节点
{
head=p;
p->next=0;
return head;
}
if(head->data>=p->data)//非空链表,插入到链表首节点
{
p->next=head;
head=p;
return head;
}
p2=p1=head;
while(p2->next&&p2->data<p->data)//找到要插入的位置
{
p1=p2;
p2=p2->next;
}
if(p2->data<p->data)//插入链表尾
{
p2->next=p;
p->next=0;
}
else//插入在p1和p2所指向的节点之间
{
p->next=p2;
p1->next=p;
}
return head;
}
node *Create_sort(void)//产生一条有序链表
{
node *p1,*head=NULL;
int a;
printf("产生一条有序链表,请输入数据,以-1结束:\n");
scanf("%d",&a);
while(a!=-1)
{
p1=(node*)malloc(sizeof(node));//产生一个新的节点
p1->data=a;
head=Insert(head,p1);//将新节点插入表中
scanf("%d",&a);
}
return head;
}
void deletechain(node *head)//释放各节点占用的内存
{
node *p1;
while(head)
{
p1=head;
head=head->next;
free((void*)p1);
}
}
int main()
{
node *head;
int num;
head=Create();//产生一条无序链表 1,3,2,5,-1
Print(head);//输出各节点数据
printf("输入要删除节点上的整数:\n");
scanf("%d",&num);
head=Delete_one_node(head,num);//删除链表上具有指定的节点 2,1
Print(head);
node *p1=(node*)malloc(sizeof(node));
p1->data=4;
head=Insert(head,p1);//将新节点插入链表中
Print(head);
deletechain(head);//释放整个链表的节点空间
head=Create_sort();//产生一条有序链表 1,3,2,5,-1
Print(head);
deletechain(head);//释放各节点空间
return 0;
}
吐槽:链表真tmd难。。