当前位置:文档之家› 双向链表和循环链表

双向链表和循环链表


头结点
p s
4.3 在结点p后面插入一个新结点s(不准引入新指针)
s->next=p->next
p->next->prior=s;
p->next=s;
^
s->prior=p 或者
s->prior=p
头结点
s->next=p->next
p->next->prior=s
p
p->next=s
s
5、删除p后面的结点
node *temp=new node; temp->data=i; temp->next=tail->next; tail->next=temp; tail=temp; }
node *head=tail->next; node *p=head; int count=1; int n; cin>>n;
}
}
5、删除p后面的结点 不准引入其他指针变量经常这样考察 if(p->next!=0) {
if(p->next->next==0)
p
{
delete p->next;
p->next=0;
}
else
p
{
p=p->next;
p->prior->next= p->next;
p->next->prior=p->prior;
TB->next=HA
delete HB
6、循环链表的合并
||||
HA
尾指针TA
||||
HB
尾指针TB
设立了尾指针,对于单循环链表的合并非常方便
TA->next=HB->next TB->next=HA delete HB
思考:如果HB表中 只有头结点呢?这样
写还正确吗?
双向链表
1、定义:结点中不仅有指向后继的指针next,还有 指向前驱的指针prior的链表称为双向链表。
while(head!=head->next) { while(count<n-1) { count++; p=p->next; } //此时p指向出列者的前驱 //删除p的后继 node *q=p->next;
头结点
s->next=0; s->prior=p; p->next=s;
^
p s
4、插入操作
4.2 在结点p(p不是尾结点)后面插入一个新结点s
^ 头结点
p
s
4、插入操作
4.2 在结点p(p不是尾结点)后面插入一个新结点s
^
引入一个指针q q=p->next s->next=q q->prior=s p->next=s s->prior=p
数据1
数据n

数据2 数据3
4、循环链表的初始化
头指针Head |||||||||||||||||||
即:Head->next=Head 则以下语句可以判断循环链表是否为空:
if(Head->next==Head) cout<<"链表为空"<<endl;
else cout<<"链表不空"<<endl;
delete p;
}
}
• 在前面我们介绍的list模板,在内部采取的 就是双向循环链表。采用双向循环链表使 得链表的倒置非常容易,只要把最后一个 结点作为第一个结点就行了。
• 总结:对于循环链表中插入、删除某个结 点经常是考察的知识点,尤其是不允许加 入新的指针变量。
思考题:
一、判断题 1、双向链表从任何一个结点出发,都能访问
p->next=r;
r->prior=p;
delete q;
}
5、删除p后面的结点
• 综合两种情况
if(p->next!=0)
{
q=p->next;
if(q->next==0)
p
{
p->next=0;
delete q;
}
else
{
r=q->next;
p->next=r;
p
r->prior=p;
delete q;
循环链表和双向链表
1、为什么引入循环链表和双向链表?这需要从单链 表的优点和缺点谈起。
2、单链表的优点:在插入和删除结点时不需要移动 大量其他结点。
3、单链表的缺点:如果有指向某个结点的指针p, 访问该结点后面的结点比较容易,但是不能访问 其前面的结点(必须从头结点开始访问),因为 单链表结点中没有指向前驱结点的指针
int data; node *next; }; ///
int main(int argc, char* argv[]) {
node *tail=new node; tail->next=tail; tail->data=1; int length=15; for(int i=2;i<=length;i++) {//生成约瑟夫环
到所有结点........( ) 2、循环链表从任何一个结点出发,都能访问
到所有结点........( )
二、程序设计题
有15个人围成一圈,顺序从1到15编号。 从第一个人开始报数,凡报到n的人退出 圈子。用C++语言写出程序,输入 n(n>=1)的值,输出最后留在圈子里的人 的编号
解决方法:采取循环链表的方法解决。 #include<iostream> using namespace std; struct node {
struct node { DataType data; node *prior;//指向前驱 node *next;//指向后继 }; 2、特点:由某个结点可方便地找到其前驱和后继。
3、形态 结点形态
prior 数据 next 双向链表形态:
^
头结点
4、插入操作
4.1 在结点p(p是尾结点)后面插入一个新结点s
5、遍历循环链表 LinkNode p; p=Head->next; while(p!=Head) { cout<<p->data<<" "; p=p->next; }
6、循环链表的合并
||||
HA
尾指针TA
||||
HB
尾指针TB
设立了尾指针,对于非空的单循环链表的合并非常
方便
TA->next=HB->next
5.1 p后面只有一个结点
if(p->next!=0)
{
q=p->next;
p
if(q->next==0)
{
p->next=0;
delete q;
}
}
5、删除p后面的结点
5.2 p后面有多个结点
if(p->next!=0)
p
{
q=p->next;
if(q->next!=0)
{
r=q->next;
p
4、循环链表和双向链表的引入使得从某个结点访问 其前驱和后继都成为可能。
循环链表
1、定义 循环链表是将链表的最后的一个结点的指 针域指向该链表的头结点,由此整个链表 形成一个环。
2、特点 从循环链表的任一结点出发均可以找到其 它结点
3、循环链表的形态
头指针Hea
相关主题