链表——线性表的链式表示

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


单链表

将每个结点放在一个独立的存储单元中,结点间的逻辑关系依靠存储单元中附加的指针来给出。结点的存储单元在物理位置可以相邻也可以不相邻。
结点由两部分组成:数据字段+指针字段(后继元素的地址)
链表结点图示
首元结点:存储第一个数据元素的结点
头节点:是首元结点之前附设的一个结点。

在这里插入图片描述

单链表示意图
头指针是指向链表中第一个结点。
单链表可由一个头指针唯一确定,能够标识一个单链表,也常做链名字。
头节点的意义:使得 在表头位置上进行插入和删除和在其他结点位置上是完全一致的(不用修改头指针)
在这里插入图片描述

数据域:p->data或(*p).data
指针域:p->next或(*p).next

遍历
Node*p=head->next;//工作指针p指向首元结点 
cout<<"traverse:";
while(p!=NULL)
{
	cout<<p->data<<" ";
	p=p->next;//向后移动指针 
 } 

时间复杂度O(n),空间复杂度O(1)
求表长

查找
Node*p=head->next;//工作指针p指向首元结点 
int count=0;//首元结点的位序为0 
while(p!=NULL&&p->data!=value)
{
	p=p->next;
	count++;
}
if(p=NULL)return -1;//查找失败返回-1,这里-1并非头节点 
else return count;//查找成功,count为元素的位序 

空间复杂度O(n),空间复杂度O(1)

插入
*s结点插入到*p之前:

s->next=p->next;
p->next=s;

temp=p->data;//交换数据域部分
p->data=s->data;
s->data=temp;
*p之前插入元素为value的结点:

pre=head;
while(pre!=NULL&&pre->next!=p)
pre=pre->next;//查找p的前驱

if(!pre)
{
	cout<<"不存在*p结点";
	exit(0);
 } 
s=new Node<elemType>();//创建新结点
s->data=value;//设置新结点的元素值
s->next=pre->next;//或用s->next=p;
pre->next=s;//插入新结点
删除
删除单链表上的第i个结点:
if(i<0)
{
	cout>>" 参数错误";
	exit(0);
}
pre=head;count=1;
while(pre->next&&count<i)//查找第i-1个结点
{
	pre=pre->next;
	count++;
}
if(pre->next==NULL)
{
	cout<<"删除位置不正确";
	exit(0); 
}
q=pre->next;
pre->next=q->next;//从链表中删除
delete q;//释放被删除结点
头插法创建(实现逆置)

头插法是在链表的头部插入结点建立单链表,也就是每次将新增结点插入在头节点之后,首元结点之前。创建的链表与输入顺序相反。

逆置单链表
Node*p,*tmp;
p=head->next;//p为工作指针指向首元结点
head->next=NULL;//头结点的指针域置空,构成空链表
while(p)
{
	tmp=p->next;//暂存p的后继
	p->next=head->next;
	head->next=p;//结点p插入到头结点的后面
	p=tmp;//继续处理下一个结点
}
尾插法

尾插法是单链表的尾部插入结点建立单链表,尾指针tail将派上用场。创建的链表与输入顺序相同

链表的特点*

(1)不要求用地址连续的存储空间存储,每个结点在运行时动态生成。结点的存储空间在物理位置上可以相邻,也可以不相邻﹔
(2)插入和删除操作不需要移动元素,只需修改指针,满足经常插入和删除结点的需求﹔
(3)链表不具备顺序表随机存取的优点﹔
(4)空间开销比较大,因链表结点增加了指示元素间关系的指针域
(5)链表是存储动态变化数据的理想选择。

双链表

如果某链表经常进行查找结点前驱的操作,我们希望查找前驱的时间复杂度也达到O(1),这时可以用空间换时间∶即每个结点再增加一个指向前驱的指针域prior,使链表可以进行双向查找,这种链表称为双向链表。
·每个结点附加了两个指针字段,如prior和next
在这里插入图片描述

p前插入s
s->prior=p->prior;//1.p原先的前驱成为s的前驱
p->prior->next=s;//2.s成为p原先的前驱的后继
s->next=p;//3.s的后继是p
p->prior=s;//4。修改p的前驱为s
语句顺序:4一定在12的后面
删除p

在这里插入图片描述

p->prior->next=p->next;
p->next->prior=p->prior;
delete p;//释放p

单循环链表

通常单循环链表不带头结点,且往往只设尾指针
在这里插入图片描述
用一个指向尾结点的尾指针来标识单循环链表,好处是既方便查找表尾结点又方便查找首元结点。
在这里插入图片描述
在这里插入图片描述
判断空循环链表:head->next=head;

双循环链表

双循环链表头结点的prior字段给出尾结点的地址,
尾结点的next字段给出头结点的地址。
在这里插入图片描述
在这里插入图片描述
判断双循环链表:head->next=head 和 head->prior=head;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值