双向链表 PPT课件

合集下载

双向循环链表操作-二叉树和树操作-图的创建及相关操作的实现(7)

双向循环链表操作-二叉树和树操作-图的创建及相关操作的实现(7)
p=getNode(idx); 3、 newNode.prev.next=newNode;
p.prev=newNode;
精选ppt
5
输入节点数据具体操作
找到下标,对其进行赋值,再将其数据输进去
System.out.println("请输入各条边(顶点在数组中的下标)及边的权重: "); for(int i=0;i<edgeNumber;i++){
把有向图转换为矩阵输出
CSNode BFSTree(){} 广度优先生成树
levelOrder(CSNode root){} 层次遍历生成树
Void path(){}
处理俩点路径问题
int[][] floyd(){}
判断出是否存在路径
void Floyd(){}
俩点之间的最短路径
class CSNode<AnyType> 孩子兄弟链表二叉树节点类 class Ver<AnyType>图的定点类 class Arc<AnyType> 图的邻接点类
在已经构建节点类的前提下:构建CourseDesign双向循环链表类,并 在这儿创建一个头结点和尾节点。定义数组大小变量,以及链表的左右 节点为空。
精选ppt
4
插入第i个节点思路
首先要获取到要针对的节点
能操作,最后给 节点赋值。
位置然后 才
1、创建新节点newNode Node<AnyType> newNode=new Node<AnyType>(x,p.prev,p); 2、Node<AnyType> p;
public void addFirst(AnyType data){ add(0,data);

图文详解双向链表原理

图文详解双向链表原理

图⽂详解双向链表原理
双向链表的主要优点是对于任意给的结点,都可以很轻易的获取其前结点和后结点,其主要缺点是每个结点需要保存next和prev两个属性,因此需要更多的空间开销,同时结点的插⼊与删除操作也将更加耗时,因为需要操作更多的指向操作。

双向链表单个节点结构:
双向链表节点
双向链表的数据结构:
双向链表数据结构
双向链表的插⼊操作
插⼊数据到链表尾部
链表尾部插⼊数据
插⼊数据到链表中间
链表中部插⼊数据
双向列表删除操作
删除链表尾部数据
删除尾部数据
删除链表中间数据
删除中间数据
循环双向列表设计
循环双向链表是在普通双向链表基础上进化得到的。

在普通的双向链表中,如果我们要获取最后⼀个节点的时候,我们只能从头开始遍历,⼀直遍历到最后才能够拿到最后⼀个节点的数据。

⽽循环双向链表会把header的prev指向最后⼀个节点,最后⼀个节点next指向header。

其数据结构如图所⽰:
循环双向链表
循环链表的添加、删除和普通的双向链表是⼀模⼀样的,这⾥就不再赘述。

链表课件(51PPT)高中信息技术浙教版(2019)选修1

链表课件(51PPT)高中信息技术浙教版(2019)选修1

链表的基本操作——链表访问
Lianbiao de jibencaozuo——linabiaofangwen
链表的访问
链表只能通过头指针(head) 进行访问,其他节点通过节点 间的指针依次访问。即链表无 法随机访问,只能进行顺序访 问。
链表的基本操作——链表访问
Lianbiao de jibencaozuo——linabiaofangwen
1.使用python 的二维列表来模拟单向链表,如下代码创建了 一个拥有4个节点的链表a: a=[[“hello”,1],[“china”,3],[“Olympics”,-1], [“winter”,2]] head=0 ①a[1][1]的值为: D A.1 B.2 C.0 D.3
②a[1][1]的含义是什么? china后面指向的下一个节点是[“winter”,2]
print(a[p][0], end="->") p = a[p][1] print(a[p][0]) 执行上述语句后,程序输出的结果为(3->7->2->1 )
链表的基本操作——链表插入
Lianbiao de jibencaozuo——lianbiaocharu
链表元素的插入 思想:当需要在链表中某个位置中插入一个新元素时,只需将元素添加在尾部,并改动指针值
现有链表a=[[“t”,2],[“y”,0],[“o”,-1]],要实现分别在头部(插入p), 中间(在t后面插入h)和尾部(插入n)插入新节点,最终形成链表 a=[[“t”,4],[“y”,0],[“o”,5],[“p”,1],[“h”,2],[“n”,-1]],请思考形成 过程,并尝试用代码实现。
h
n
2
-1

双向链表

双向链表

第8讲 双向链表● 循环单链表的出现,虽然能够实现从任一结点出发沿着链能找到其前趋结点,但时间耗费是O (n) 。

● 如果希望从表中快速确定某一个结点的前趋,另一个解决方法就是在单链表的每个结点里再增加一个指向其前趋的指针域prior 。

这样形成的链表中就有两条方向不同的链,我们称之为双向链表。

● 双向链表的结构定义如下:typedef struct DNode{ ElemType data ;struct DNode *prior ,*next ;}DNode, * DoubleList ;● 双向链表的结点结构如图所示。

图:双链表的结点结构注:● 双向链表也是由头指针唯一确定的,● 增加头结点能使双链表的某些运算变得方便● 由于在双向链表中既有前向链又有后向链,寻找任一个结点的直接前驱结点与直接后继结点变得非常方便。

● 设指针p 指向双链表中某一结点,则有下式成立:p->prior->next = p = p->next->prior●在双向链表中,那些只涉及后继指针的算法,如求表长度、取元素、元素定位等,与单链表中相应的算法相同,● 但对于前插和删除操作则涉及到前驱和后继两个方向的指针变化,因此与单链表中的算法不同。

1、 双向链表的前插操作【算法思想】欲在双向链表第i 个结点之前插入一个的新的结点,则指针的变化情况如图所示:… p …s->prior=p->prior; ①p->prior->next=s;②s->next=p; ③p->prior=s;④【算法描述】int DlinkIns(DoubleList L,int i,ElemType e){DNode *s,*p;… /*先检查待插入的位置i是否合法(实现方法同单链表的前插操作)*/… /*若位置i合法,则找到第i个结点并让指针p指向它*/s=(DNode*)malloc(sizeof(DNode));if (s){ s->data=e;s->prior=p->prior; ①p->prior->next=s; ②s->next=p; ③p->prior=s; ④r eturn TRUE;}else return FALSE;}2、双向链表的删除操作【算法思想】欲删除双向链表中的第i个结点,则指针的变化情况如图所示:p->prior->next=p->next; ①p->next->prior=p->prior; ②free(p);【算法描述】int DlinkDel(DoubleList L,int i,ElemType *e){DNode *p;… /*先检查待插入的位置i 是否合法(实现方法同单链表的删除操作)*/… /*若位置i 合法,则找到第i 个结点并让指针p 指向它*/*e=p->data;p->prior->next=p->next; ①p->next->prior=p->prior; ②free(p);return TRUE;}3、 双向循环链表双向链表可以有循环表,称为双向循环链表。

链表,单链表,双链表,循环链表共88页

链表,单链表,双链表,循环链表共88页
链表,单链表,双链表,循环链表
56、死去何所道,托体同山阿。 57、春秋多佳日,登高赋新诗。 58、种豆南山下,草盛豆苗稀。晨兴 理荒秽 ,带月 荷锄归 。道狭 草木长 ,夕露 沾我衣 。衣沾 不足惜 ,但使 愿无违 。 59、相见无杂言,但道桑麻长。 60、迢迢新秋夕,亭亭月将圆。
பைடு நூலகம்
31、只有永远躺在泥坑里的人,才不会再掉进坑里。——黑格尔 32、希望的灯一旦熄灭,生活刹那间变成了一片黑暗。——普列姆昌德 33、希望是人生的乳母。——科策布 34、形成天才的决定因素应该是勤奋。——郭沫若 35、学到很多东西的诀窍,就是一下子不要学很多。——洛克

链表的操作PPT课件

链表的操作PPT课件

2、free_node()函数
void free_node(link p)
{
free(p);
第5页/共20页
3、insert()函数 void insert(link p) { p->next = head; head = p; }
第6页/共20页
4、delete()函数
void delete(link p) {
link p; for (p = head; p; p = p->next)
printf("%d\n", p->item); }
第8页/共20页
6、search()函数
link search(unsigned char key) {
link p; for (p = head; p; p = p->next)
• 链表的删除操作 LIST-DELETE'(L, x) • 增加哨兵节点后,忽视在表头和表尾的边界条件,代码变得更加简洁。 • 算法描述如下:
next[prev[x]] = next[x] prev[next[x]] = prev[x]
第19页/共20页
感谢您的观看!
第20页/共20页
第16页/共20页
1.2 双向链表
• 链表的搜索操作 LIST-SEARCH'(L, k) • 链表的搜索代码,对NULL和head[L]的引用做了改动。 • 算法描述如下:
x = next[nil[L]] while x ≠ nil[L] and key[x] ≠ k
do x = next[x] return x
x = head[L] while x ≠ NULL and key[x] ≠ k

双向链表的建立与释放

双向链表的建立与释放

双向链表的建立与释放
首先我们先通过例子来讨论双向链表的建立方法和释放方法。

1. 例子
例如有下列四个结点:
图3-16 双向链表结点示例
我们现在想要把它们链接成一个双向链表,其运行过程如下图所示。

NULL
图3-17 双向链表结点的链接示例
双向链表的释放和单链表的释放方式一样,从首结点开始一个一个的将结点释放,直到下一个结点的指针指向NULL (即到达尾端)为止。

2. 算法思想
(1) 双向链表的建立:
首先声明一个双向链表的首结点head ,并将head->next 和head->prior 设为NULL 。

每输入一个数据就申请一个结点的内存空间,并赋给指针变量new ,把new->next 和new->prior 设为NULL ,并且链接到之前链表的尾端,再将new->prior 指向原链表的尾端。

(2) 双向链表的输出:
和单链表相同。

(3) 双向链表的释放:
和单链表相同。

双向链表

双向链表

准备:动态内存分配一、为什么用动态内存分配但我们未学习链表的时候,如果要存储数量比较多的同类型或同结构的数据的时候,总是使用一个数组。

比如说我们要存储一个班级学生的某科分数,总是定义一个float型(存在0.5分)数组:float score[30];但是,在使用数组的时候,总有一个问题困扰着我们:数组应该有多大?在很多的情况下,你并不能确定要使用多大的数组,比如上例,你可能并不知道该班级的学生的人数,那么你就要把数组定义得足够大。

这样,你的程序在运行时就申请了固定大小的你认为足够大的内存空间。

即使你知道该班级的学生数,但是如果因为某种特殊原因人数有增加或者减少,你又必须重新去修改程序,扩大数组的存储范围。

这种分配固定大小的内存分配方法称之为静态内存分配。

但是这种内存分配的方法存在比较严重的缺陷,特别是处理某些问题时:在大多数情况下会浪费大量的内存空间,在少数情况下,当你定义的数组不够大时,可能引起下标越界错误,甚至导致严重后果。

那么有没有其它的方法来解决这样的外呢体呢?有,那就是动态内存分配。

所谓动态内存分配就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。

动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。

从以上动、静态内存分配比较可以知道动态内存分配相对于景泰内存分配的特点:1、不需要预先分配存储空间;2、分配的空间可以根据程序的需要扩大或缩小。

二、如何实现动态内存分配及其管理要实现根据程序的需要动态分配存储空间,就必须用到以下几个函数1、malloc函数malloc函数的原型为:void *malloc (unsigned int size)其作用是在内存的动态存储区中分配一个长度为size的连续空间。

其参数是一个无符号整形数,返回值是一个指向所分配的连续存储域的起始地址的指针。

还有一点必须注意的是,当函数未能成功分配存储空间(如内存不足)就会返回一个NULL指针。

双向链表的基本操作

双向链表的基本操作

双向链表的基本操作前⾯学习了如何创建⼀个,本节学习有关双向的⼀些基本操作,即如何在双向链表中添加、删除、查找或更改数据元素。

本节知识基于已熟练掌握双向链表创建过程的基础上,我们继续上节所创建的双向链表来学习本节内容,创建好的双向链表如图 1 所⽰:图 1 双向链表⽰意图双向链表添加节点根据数据添加到双向链表中的位置不同,可细分为以下 3 种情况:添加⾄表头将新数据元素添加到表头,只需要将该元素与表头元素建⽴双层逻辑关系即可。

换句话说,假设新元素节点为 temp,表头节点为 head,则需要做以下 2 步操作即可:1. temp->next=head; head->prior=temp;2. 将 head 移⾄ temp,重新指向新的表头;例如,将新元素 7 添加⾄双链表的表头,则实现过程如图 2 所⽰:图 2 添加元素⾄双向链表的表头添加⾄表的中间位置同添加数据类似,双向链表中间位置添加数据需要经过以下 2 个步骤,如图 3 所⽰:1. 新节点先与其直接后继节点建⽴双层逻辑关系;2. 新节点的直接前驱节点与之建⽴双层逻辑关系;图 3 双向链表中间位置添加数据元素添加⾄表尾与添加到表头是⼀个道理,实现过程如下(如图 4 所⽰):1. 找到双链表中最后⼀个节点;2. 让新节点与最后⼀个节点进⾏双层逻辑关系;图 4 双向链表尾部添加数据元素因此,我们可以试着编写双向链表添加数据的 C 语⾔代码,参考代码如下:1. line * insertLine(line * head,int data,int add){2. //新建数据域为data的结点3. line * temp=(line*)malloc(sizeof(line));4. temp->data=data;5. temp->prior=NULL;6. temp->next=NULL;7. //插⼊到链表头,要特殊考虑8. if (add==1) {9. temp->next=head;10. head->prior=temp;11. head=temp;12. }else{13. line * body=head;14. //找到要插⼊位置的前⼀个结点15. for (int i=1; i<add-1; i++) {16. body=body->next;17. }18. //判断条件为真,说明插⼊位置为链表尾19. if (body->next==NULL) {20. body->next=temp;21. temp->prior=body;22. }else{23. body->next->prior=temp;24. temp->next=body->next;25. body->next=temp;26. temp->prior=body;27. }28. }29. return head;30. }双向链表删除节点双链表删除结点时,只需遍历链表找到要删除的结点,然后将该节点从表中摘除即可。

双向链表课件-浙教版(2019)高中信息技术选修1

双向链表课件-浙教版(2019)高中信息技术选修1
def shuchu(a,head): p=head while a[p][2]!=-1 print(a[p][0],end=“---->”) p=a[p][2]
print(a[p][0])
三、双向链表节点的插入
链表节点的插入指的是根据新输入的实际数据形成节点,然后修改新节点与 其前驱与后继节点的指针,将新节点插入到链表的正确位置。 从链表头部插入一个新节点(头插法):例如,在双向链表a的头部插入一个新节点 node的代码如下:
节点 (由数据区域和前驱节点指针、后继节点指针构成)
双向链表的特性
双向链表中当节点中prev指向为-1(即指向为空)时,表示该节点为链表 中的首个节点;相对的,当节点中next指向为-1时,表示该节点为链表中 的最后一个节点。
下图所示为用二维列表表示一个长度为6的双向链表
^ data 1
data 2
创建一个空链表dblinklist的 代码如下: dblinklist=[] head=-1
创建一个拥有2个节点的双向链表 dblinklist的代码如下: dblinklist=[[6,-1,1],[8,0,-1],] head=0
二、双向链表节点的访问
链表节点只能通过头指针(head)进行访问,其他节点通过节点间的next指针 依次访问。 可以设计如下自定义函数输出链表的所有节点:
a[a[p][2]][1]=len(a)-1 a[p][2]=_l_e_n_(_a_)_-1 display(a,head)
谢谢
2.Python中可以使用二维列表来模拟双向链表,用包含三个元素的 列表来表示每一个节点,其中第1个元素存储数据,第二、三个元素 分别存储前驱指针prev和后继指针next;同时双向链表使用头指针 head指向第一个节点在列表中的索引。 下列代码创建了一个双向链表a: a=[[2,2,5],[8,0,5],[0,-1,0],[1,-1,2],[5,5,-1],[3,0,-1]] head=2 则该双向链表a的节点数量为:A

循环链表和双向链表

循环链表和双向链表

b.head->next = NULL; //此时,b中已只剩第一个结点(头), 为其置空表标志
return k; //返回结果链表中的元素个数
}
为了进一步说明上述程序,举一个程序运行的例子, 其各次循环的运行结果如图5-6所示
p
7 0 3 2 -9 3 1 5
^
(a)A(x)=p5(x)=7+3x2-9x3+x5,进入循环前
该程序不断比较A链和B链中的一对结点的指数值 (称其为当前结点)。开始时A链和B链中参加比较
的当前结点都是它们的第一个元素。
主循环while结束后,可能出现下列3种情况:①A
链和B链同时被处理完;②只有B链处理完;③只有A
链处理完。 对第一和第二种情况,不需要“善后”处理。对第 三种情况,B链中尚有未被处理完的结点,需将其挂 接在结果链的尾部。循环外的“if(q 不为空)将q
p = p->next; } // if (x==0) … else … q0 = q; q = q->next; delete q0; //将q所指结点从表中删除并释放,令q新指向原所 指的下一个 } // if (p->exp > q->exp ) … else … } //while if (q!=NULL) p0->next = q;
为处理方便,在具体存储多项式时,我们规定:
所存储的多项式已约简,即已合并同类项,不 保留0系数项,各项按指数的升序排列。 (二)多项式加法实现—直接操作链表 为操作方便,我采用带头结点的非循环链表,下面给 出一个例子说明多项式的这种表示法。
设有一个一元5次多项式: P5(x)=7+3x-9x3+x5

线性表之双向链表

线性表之双向链表

线性表之双向链表⼀,双向链表的基础知识1.双向链表的概念 双向链表是在单链表的每个结点中,再设置⼀个指向其前驱结点的指针域。

所以在双向链表的每个结点中都有两个指针域,⼀个指向其前驱结点,⼀个指向其后继结点。

2.双向链表实现的难点每⼀个数据元素有两个指针域,⼀个指向其前驱结点,⼀个指向其后继结点。

第⼀个结点的前驱为NULL,最后⼀个节点的后继为NULL。

⼆,双向链表的实现1.双向链表的基本功能(DoubleLinkList.h)# ifndef DOUBLE_LINK_LIST# define DOUBLE_LINK_LIST/* 业务节点 */typedef void Node;/* 链表节点(被包含) */typedef struct DoubleNode{struct DoubleNode * prev;struct DoubleNode * next;}DoubleNode;/* 双向链表 */typedef struct DoubleLinkList{Node * ptr;DoubleNode header;DoubleNode slider;int length;}DoubleLinkList;/* 创建链表 */DoubleLinkList * createList();/* 清空链表 */void clear(DoubleLinkList * list);/* 销毁链表 */void destory(DoubleLinkList * list);/* 链表长度 */int length(DoubleLinkList * list);/* 链表是否为空 */int empty(DoubleLinkList * list);/* 插⼊链表 */void insert(DoubleLinkList * list, int pos, Node * node);/* 删除链表 */Node * del(DoubleLinkList * list, int pos);/* 删除某个元素 */Node * delNode(DoubleLinkList * list, Node * node);/* 获取链表 */Node * get(DoubleLinkList * list, int pos);/* 重置游标 */void resetSlider(DoubleLinkList * list);/* 游标下移 */Node * next(DoubleLinkList * list);/* 游标上移 */Node * prev(DoubleLinkList * list);/* 获取当前游标的结点 */Node * current(DoubleLinkList * list);# endif2.双向链表基本功能的实现(DoubleLinkList.c)# include<stdio.h># include<stdlib.h># include"DoubleLinkList.h"/* 创建链表 */DoubleLinkList * createList(){DoubleLinkList * list = (DoubleLinkList *)malloc(sizeof(DoubleLinkList)); /* 初始化头指针 */list->ptr = &(list->header);/* 初始化头结点 */list->header.next = NULL;list->header.prev = NULL;/* 初始化游标 */list->slider.next = NULL;/* 初始化链表长度 */list->length = 0;return list;}/* 清空链表 */void clear(DoubleLinkList * list){/* 置空头结点 */list->header.next = NULL;list->header.prev = NULL;/* 置空游标 */list->slider.next = NULL;/* 置空链表长度 */list->length = 0;}/* 销毁链表 */void destory(DoubleLinkList * list){if (list != NULL){free(list);list = NULL;}}/* 链表长度 */int length(DoubleLinkList * list){return list->length;}/* 链表是否为空 */int empty(DoubleLinkList * list){if (list->length <= 0){return1;}else {return0;}}/* 插⼊链表 */void insert(DoubleLinkList * list, int pos, Node * node){if (list == NULL){printf("链表为NULL\n");return;}/* 判断插⼊位置合法性 */pos = pos < 0 ? 0 : pos;pos = pos > length(list) ? length(list) : pos;/* 将业务结点转换为链表结点 */DoubleNode * _node = (DoubleNode *)node;/* 判断是否是第⼀次插⼊ */if (length(list) == 0){list->header.next = _node;_node->prev = NULL;_node->next = NULL;list->length++;return;}/* 判断是否是插⼊头部 */if (pos == 0){list->header.next->prev = _node;_node->next = list->header.next;list->header.next = _node;_node->prev = NULL;}else {DoubleNode * posNode = list->header.next; DoubleNode * previous = posNode;for (int i = 0; i < pos; i++){previous = posNode;posNode = posNode->next;}previous->next = _node;_node->prev = previous;posNode->prev = _node;_node->next = posNode;}list->length++;}/* 删除链表 */Node * del(DoubleLinkList * list, int pos){if (list == NULL){printf("链表为NULL\n");return NULL;}if (length(list) == 0){printf("链表长度为0,删除失败\n");return NULL;}/* 判断删除位置合法性 */pos = pos < 0 ? 0 : pos;pos = pos > length(list) ? length(list) : pos;/* 定义删除的返回结点 */DoubleNode * result = NULL;/* 判断是否删除第⼀个 */if (pos == 0){result = list->header.next;list->header.next = list->header.next->next; list->header.next->prev = NULL;}else {DoubleNode * posNode = list->header.next; DoubleNode * previous = posNode;for (int i = 0; i < pos; i++){previous = posNode;posNode = posNode->next;}result = posNode;previous->next = posNode->next;posNode->next->prev = previous;}list->length--;return result;}/* 删除某个元素 */Node * delNode(DoubleLinkList * list, Node * node) {/* 找出该元素位置 */int pos = -1;/* 遍历寻找 */for (int i = 0; i < length(list); i++){Node * tmp = get(list, i);if (tmp == node){pos = i;}}/* 如果未找到退出 */if (pos == -1){printf("未找到该元素\n");return NULL;}/* 找到后删除 */Node * result = del(list, pos);return result;}/* 获取链表 */Node * get(DoubleLinkList * list, int pos){DoubleNode * posNode = list->header.next; for (int i = 0; i < pos; i++){posNode = posNode->next;}return posNode;}/* 重置游标 */void resetSlider(DoubleLinkList * list){list->slider.next = list->header.next;}/* 游标下移 */Node * next(DoubleLinkList * list){if (list->slider.next->next != NULL){DoubleNode * result = list->slider.next; list->slider.next = list->slider.next->next;return result;}return NULL;}/* 游标上移 */Node * prev(DoubleLinkList * list){if (list->slider.next->prev != NULL){DoubleNode * result = list->slider.next; list->slider.next = list->slider.next->prev;return result;}return NULL;}/* 获取当前游标的结点 */Node * current(DoubleLinkList * list){return list->slider.next;}3.双向链表的测试# define _CRT_SECURE_NO_WARNINGS# include<stdio.h># include<string.h># include"DoubleLinkList.h"typedef struct Student{DoubleNode next;char name[64];int age;}Student;int main(){Student s1;strcpy(, "刘备");s1.age = 56;Student s2;strcpy(, "关⽻");s2.age = 40;Student s3;strcpy(, "张飞");s3.age = 38;/* 创建双向链表 */DoubleLinkList * list = createList();/* 插⼊数据 */insert(list, 0, &s1);insert(list, 0, &s2);insert(list, 0, &s3);/* 遍历 */printf("##############基本遍历##############\n");for (int i = 0; i < length(list); i++){Student * stu = (Student *)get(list,i);printf("name = %s,age = %d\n", stu->name, stu->age);}/* 删除 */del(list, 0);printf("##############删除0号位置后遍历##############\n"); for (int i = 0; i < length(list); i++){Student * stu = (Student *)get(list, i);printf("name = %s,age = %d\n", stu->name, stu->age);}/* 删除节点 */delNode(list,&s2);printf("##############删除s2后遍历##############\n");for (int i = 0; i < length(list); i++){Student * stu = (Student *)get(list, i);printf("name = %s,age = %d\n", stu->name, stu->age);}/* 重置游标 */resetSlider(list);Student * ss1 = (Student *)current(list);printf("##############重置游标##############\n");printf("name = %s,age = %d\n", ss1->name, ss1->age);/* 游标下移 */next(list);Student * ss2 = (Student *)current(list);printf("##############游标下移##############\n");printf("name = %s,age = %d\n", ss2->name, ss2->age);next(list);Student * ss3 = (Student *)current(list);printf("##############游标下移##############\n");printf("name = %s,age = %d\n", ss3->name, ss3->age);/* 游标上移 */prev(list);ss2 = (Student *)current(list);printf("##############游标上移##############\n");printf("name = %s,age = %d\n", ss2->name, ss2->age);}。

双向循环链表--清华大学课程讲义-数据结构(PPT)

双向循环链表--清华大学课程讲义-数据结构(PPT)
2013-9-10 4
2013-9-10
5
2013-9-10 2
带头结点的双向循环链表 :
first
e0
e1
current

en-1
first 空表 游标结点: * current 游标结点的前驱结点: * ( current -> lLink ) 游标结点的后继结点: * ( current -> rLink )
2013-9late <class Type> class DblList { public: DblList ( Type uniqueVal ); ~DblList ( ); int Length ( ) const; int IsEmpty ( ) { return first->rLink==first ;} int Find ( const Type & target ); Type getData ( ) const; void Firster ( ) { current = first; } int First ( ); int Next ( ); int Prior ( ); int operator ! ( ) { return current != NULL;} void Insert ( const Type & value ); void Remove ( ) ; private: DblNode <Type> * first, * current; }
调查结果:
讲课进度: 偏快 27 人 适中 20 人 偏慢 2 人 课程难易: 太简单 1 人 偏难 9 人 太繁 1 人 讲解方法: 多讲理论、原理、方法,少讲具体程序 少讲理论,多讲程序和C++内容 多讲具体应用的完整实例 其他: 规定交作业时间,促进学生做作业; 作业太多,要少而精; 最好能现场编程、调试;

第四章双向链表

第四章双向链表
第四章 双向链表
双向链表
双向链表是指在前驱和后继方向都能 游历(遍历)的线性链表。 双向链表每个结点结构:
lLink 前驱方向 data rLink 后继方向
双向链表通常采用带表头结点的循环 链表形式。
双向链表
A
B
C
Head
first
first
非空表
空表
结点指向 p == p->lLink->rLink == p->rLink>lLink rLink lLink
链表的应用
链表队列 链表堆栈
Project #2
事件驱动模拟pp.190
银行排队的数学模型的实现
问题
银行有n个窗口对外营业,每个窗口一次只能 接待一个客户 客户的到达时间和处理业务的时间不同(可随 机产生) 利用链表队列模拟总的处理过程和处理时间 假设
不允许插队 不同客户的交接时间忽略不计
策略I
2-3人合作 Deadline: Monday, Oct. 17
AnnouncHale Waihona Puke mentOct. 10-14
PG conference, Macau
代课
计忠平 老师
课程作业上载
\Homework#2 \Project#2
Q&A
p->lLink
p
p->rLink
class CDNode
class CDNode { public: double m_dData; CDNode *m_pNext, *m_pPrev; }
Methods of DNode
double GetItem(); DNode *GetPrev(); DNode *GetNext(); void SetItem(); void SetPrev(DNode *pNode); void SetNext(DNode *pNode);
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

^
非空的双向链表
环形双向链表
head
^
空的环形双向链表
head ……......
非空的环形双向链表 p->rlink->llink= p->llink->rlink= p
带表头结点的双向链表点双向链表
head ^
……......
^
非空的带表头结点双向链表
带表头结点的环形双向链表
设某个环形链表的长度大于1,且表中即无头指针 也无头结点,已知s为指向链表中某个结点的指针, 试编写算法在链表中删除s所指结点的前驱结点
s
void dele(s) NODE *s; { NODE *p,*q;
p=s; while (p->link!=s)
{ q=p; p=p->link;}
q->link=s; free(p); }
#include <stdio.h> struct node { char data;
struct node *llink,*rlink; }; typedef struct node NODE; NODE *head;
head ^
head ^
双向链表
空的双向链表 head=NULL
……......
p=p->rlink; if (p= =head)
return(1);
P->llink->rlink=p->rlink; p->rlink->llink=p->llink; free(p); return(0); }
删除双向环形链表中第k(k>0)个结点
……. for(j=0;j<k&&p!=head;j++) p=p->rlink; if(p==head) return(1); p->llink->rlink=p->rlink; p->rlink->llink=p->llink; free(p); return(0);
第二次作业
1.试编写一个求已知单链表的数据域的平均值的 函数
2.已知带有头结点的环形链表中头指针为head, 试写出删除并释放数据域值为x的所有结点的 函数
int insert_d_l(head,x,y) NODE *head; char x,y; { NODE *p,*q;
p=head->rlink; while (p!=head && p->data!=x) p=p->rlink; if (p= =head) return(1);
q=(NODE*)malloc(sizeof(NODE)); q->data=y; q->rlink=p->rlink; p->rlink=q; q->rlink->llink=q; q->llink=p; return(0); }
head 空的带表头结点环形双向链表
head ……......
非空的带表头结点环形双向链表
带表头的环形双向链表的插入
将值为y的结点插在值为x的结点之后
p
x* *
23
4
1
y
q
……......
^
1.q->rlink=p->rlink 2.p->rlink=q 3.q->rlink->llink=q 4.q->llink=p
编写在链表中s结点之前插入新结点的算法
p
s
q
• 要访问某个结点的前趋结点很麻烦,…...
• 要删除链表中一个结点时,仅给出该结点的指针 还不行……
• 在指定的结点之前插入一个新结点…..
双向链表
llink
data
rlink
• 左指针:llink 指向该结点的前趋结点
• 右指针:rlink 指向该结点的后继结点
带表头的环形双向链表的删除
1 p
* *
x
* *
……......
^
2
p->llink->rlink=p->rlink p->rlink->llink=p->llink
int delete-d-l(head,x) NODE *head; char x; { NODE *p;
p=head->rlink; while (p!=head && p->data!=x)
相关文档
最新文档