前言:本节内容主要了解链表的基本概念及特点,以及能够通过数组模拟学会链表的几种基本操作,下一节我们将通过STL模板完成链表操作,可以通过专栏进入查看下一节哦~
目录
单链表及其特点
完整链表构成
完整链表简述
创建单链表
定义节点存储结构
尾插法插入元素
遍历并显示链表内容
头插法插入元素
向链表中插入元素
删除元素
查找元素
链表基本操作完整代码
单链表及其特点
链表的种类较多,这里我们主要讲解最常见的带头结点的单链表。
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。
如图所示,链表中每个数据的存储都由以下两部分组成:
1.数据元素本身,其所在的区域称为数据域;
2.指向直接后继元素的指针,所在的区域称为指针域;
完整链表构成
1.头结点:头节点是一个不存储任何数据的结点,是为了方便找到链表位置。
2.首元结点:它是链表中称第一个存有数据的节点为首元结点,称呼没有实际意义。
3.其他结点:链表中其他的结点。
完整链表简述
注意:链表中有头结点时,头指针指向头结点;反之,若链表中没有头结点,则头指针指向首元结点。
简单的来说,链表就像一环扣一环的链子一样,当你想插入删除元素的时候,只需要找到你要插入或者删除的位置,然后解开该位置两边的环,然后将新的环连接上即可。
由于链表的特殊结构,决定了它拥有一个数组所没有的优势,那就是进行插入删除操作的时候,不需要移动元素。但是缺点就是查找元素需要从头结点开始一个一个往后找。
创建单链表
单链表在创建的时候需要先声明结点,方可创建链表,即向链表中插入元素。插入元素时,又可分为头插法和尾插法。头插法和尾插法的区别后面会通过结果展示出来。
头插法:在头结点之后插入数据,其特点是读入的数据顺序与线性表的逻辑顺序正好相反,可用来实现倒序输出一个元素序列。
尾插法:将每次插入的新结点放在链表的尾部。
定义节点存储结构
struct Node
{
int data; //保存节点中存储的数据
Node *next; //指向下一结点
};
尾插法插入元素
void Wcreate(Node *l,int n) //尾插法向链表中插入n个数字
{
Node *p,*r; //p用来指向新生成的结点。r始终指向l的终端结点。
r=l; //r指向了头节点,此时的头节点也是终端节点
int k;
for(int i=0;i<n;i++) {
cin>>k;
p=new Node; //为结点分配空间
p->data=k; //将数值存入新结点
r->next=p; //接受新的结点
r=p; //r指向终端结点
}
r->next=NULL; //l的终端结点指针域为NULL,l建立完成
}
遍历并显示链表内容
void show(Node *l)
{
Node *p;
p=l->next;
while(p!=NULL)
{
cout<<p->data<<" ";
p=p->next;
}
cout<<endl;
}
头插法插入元素
void Tcreate(Node *l,int n) //头插法向链表中插入n个数字
{
Node *p; //p用来指向新生成的结点
l->next=NULL;
int k;
for(int i=0;i<n;i++) {
cin>>k;
p=new Node; //为结点分配空间
p->data=k; //将数值存入新结点
p->next=l->next; //将l指向的地址赋值给p;
l->next=p; //头指针的指针域next指向p结点,使得p成为开始结点。
}
}
向链表中插入元素
void insert(Node *l,int k,int e)//在第k个位置后插入元素e;
{
Node *p,*r;
r=l;
if(r->next==NULL) cout<<"链表为空";
for(int i=0;i<k;i++) //找到第k个位置之前的那个位置
r=r->next;
p=new Node; //为新结点申请空间
p->data=e;
p->next=r->next;
r->next=p;
}
删除元素
void Delete(Node *l,int x) //删除第一个值为x的数。
{
Node *r,*pre;
pre=l; //记录前驱结点,防止断链
r=l->next;
while(r->data!=x)
{
pre=r; //记录该结点前一个结点
r=r->next;
}
pre->next=r->next; //将其前驱next指向其后继,实现删除
}
查找元素
//查找值为X的数是否存在,在则输出第一次出现的位置。
void Search(Node *l,int x) {
int k=1; //记录位置
Node *p;
p=l->next;
while(p->data!=x&&p->next!=NULL) {
p=p->next;
k++;
}
if(p->data!=x) cout<<"未找到"<<endl;
else cout<<"是第"<<k<<"个数字"<<endl;
}
链表基本操作完整代码
#include<iostream>
using namespace std;
struct Node
{
int data; //保存结点中存储的数据
Node *next; //指向下一结点
};
void Wcreate(Node *l,int n) //尾插法向链表中插入n个数字
{
Node *p,*r; //p用来指向新生成的节点。r始终指向l的终端节点。
r=l; //r指向了头节点,此时的头节点也是终端节点
int k;
for(int i=0;i<n;i++) {
cin>>k;
p=new Node; //为节点分配空间
p->data=k; //将数值存入新节点
r->next=p; //接受新的节点
r=p; //r指向终端节点
}
r->next=NULL; //l的终端节点指针域为NULL,l建立完成
}
void Tcreate(Node *l,int n) //头插法向链表中插入n个数字
{
Node *p; //p用来指向新生成的结点
l->next=NULL;
int k;
for(int i=0;i<n;i++) {
cin>>k;
p=new Node; //为结点分配空间
p->data=k; //将数值存入新结点
p->next=l->next; //将l指向的地址赋值给p;
l->next=p; //头指针的指针域next指向p结点,使得p成为开始结点。
}
}
void show(Node *l)
{
Node *p;
p=l->next;
while(p!=NULL)
{
cout<<p->data<<" ";
p=p->next;
}
cout<<endl;
}
void Search(Node *l,int x) //查找第一个值为X的数是否存在。
{
int k=1; //记录位置
Node *p;
p=l->next;
while(p->data!=x&&p->next!=NULL){
p=p->next;
k++;
}
if(p->data!=x) cout<<"未找到"<<endl;
else cout<<"是第"<<k<<"个数字"<<endl;
}
int main()
{
Node *L; //数据第一个数字位置是0
L=new Node;
L->next=NULL;
int n,x,m;
cin>>n;
Wcreate(L,n);
cout<<"尾插法插入结果:";
show(L);
/*
Tcreate(L,n);
cout<<"头插法插入结果:";
show(L);
cout<<"\n请输入插入的位置及元素值:"<<endl;
cin>>m>>x;
Insert(L,m,x);
show(L);
cout<<"\n请输入要删除的数值:"<<endl;
cin>>x;
Delete(L,x);
show(L);
*/
cout<<"\n请输入要查找的数值:"<<endl;
cin>>x;
Search(L,x);
return 0;
}