数学数据结构学习教案.pptx

上传人:一*** 文档编号:71934300 上传时间:2023-02-07 格式:PPTX 页数:101 大小:853.28KB
返回 下载 相关 举报
数学数据结构学习教案.pptx_第1页
第1页 / 共101页
数学数据结构学习教案.pptx_第2页
第2页 / 共101页
点击查看更多>>
资源描述

《数学数据结构学习教案.pptx》由会员分享,可在线阅读,更多相关《数学数据结构学习教案.pptx(101页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、数学数学(shxu)数据结构数据结构第一页,共101页。图2.1 线性表的逻辑(lu j)结构 2.1 线性表的概念(ginin)及运算2.1.1 线性表的逻辑(lu j)结构 第1页/共101页第二页,共101页。例如:英文字母表(A,B,Z)就是一个简单的线性表,表中的每一个英文字母是一个数据元素,每个元素之间存在唯一的顺序关系,如在英文字母表字母B的前面是字母A,而字母B的后面(hu mian)是字母C。在较为复杂的线性表中,数据元素(data elements)可由若干数据项组成,如学生成绩表中,每个学生及其各科成绩是一个数据元素,它由学号、姓名、各科成绩及平均成绩等数据项(item)

2、组成,常被称为一个记录(record),含有大量记录的线性表称为文件(file)。数据对象(data object)是性质相同的数据元素集合。第2页/共101页第三页,共101页。表2-1 车辆(chling)登记表 第3页/共101页第四页,共101页。线性表(Linear List)是由n(n0)个类型相同的数据元素a1,a2,,an组成的有限序列,记作(a1,a2,,ai-1,ai,ai+1,an)。这里的数据元素ai(1in)只是一个抽象的符号,其具体含义在不同情况下可以不同,它既可以是原子类型,也可以是结构类型但同一线性表中的数据元素必须属于同一数据对象。此外,线性表中相邻(xin

3、ln)数据元素之间存在着序偶关系,即对于非空的线性表(a1,a2,,ai-1,ai,ai+1,an),表中ai-1 领先于ai,称ai-1 是ai的直接前驱,而称ai是 ai-1的直接后继。除了第一个元素a1外,每个元素ai有且仅有一个被称为其直接前驱的结点ai-1,除了最后一个元素an外,每个元素ai有且仅有一个被称为其直接后继的结点ai+1。线性表中元素的个数n被定义为线性表的长度,n=0时称为空表。第4页/共101页第五页,共101页。线性表的特点可概括如下:同一(tngy)性:线性表由同类数据元素组成,每一个ai必须属于同一(tngy)数据对象。有穷性:线性表由有限个数据元素组成,表长

4、度就是表中数据元素的个数。有序性:线性表中表中相邻数据元素之间存在着序偶关系。由此可看出,线性表是一种最简单的数据结构,因为数据元素之间是由一前驱一后继的直观有序的关系确定;线性表又是一种最常见的数据结构,因为矩阵、数组、字符串、堆栈、队列等都符合线性条件。第5页/共101页第六页,共101页。2.1.2 线性表的抽象数据类型定义(dngy)ADT LinearList 数据元素:D=ai|aiD0,i=1,2,,n,n0,D0为某一数据对象 关系:|ai,ai+1D0,i=1,2,n-1 基本操作(cozu):(1)InitList(L)操作(cozu)前提:L为未初始化线性表。操作(coz

5、u)结果:将L初始化为空表。第6页/共101页第七页,共101页。(2)DestroyList(L)操作前提:线性表L已存在。操作结果:将L销毁。(3)ClearList(L)操作前提:线性表L已存在。操作结果:将表L置为空表。(4)EmptyList(L)操作前提:线性表L已存在。操作结果:如果(rgu)L为空表则返回真,否则返回假。第7页/共101页第八页,共101页。(5)ListLength(L)操作前提:线性表L已存在。操作结果:如果(rgu)L为空表则返回0,否则返回表中的元素个数。(6)Locate(L,e)操作前提:表L已存在,e为合法元素值。操作结果:如果(rgu)L中存在元

6、素e,则将“当前指针”指向元素e所在位置并返回真,否则返回假。(7)GetData(L,i)操作前提:表L存在,且i值合法,即1iListLength(L)。操作结果:返回线性表L中第i个元素的值。第8页/共101页第九页,共101页。(8)InsList(L,i,e)操作(cozu)前提:表L已存在,e为合法元素值且1iListLength(L)+1。操作(cozu)结果:在L中第i个位置插入新的数据元素e,L的长度加1。(9)DelList(L,i,&e)操作(cozu)前提:表L已存在且非空,1iListLength(L)。操作(cozu)结果:删除L的第i个数据元素,并用e返回其值,L

7、的长度减1。ADT LinearList 第9页/共101页第十页,共101页。2.2 线性表的顺序存储2.2.1 线性表的顺序存储结构(jigu)线性表的顺序存储是指用一组地址连续的存储单元依 次存储线性表中的各个(gg)元素,使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。采用顺序存储结构的线性表通常称为顺序表。第10页/共101页第十一页,共101页。假设线性表中有n个元素,每个元素占k个单元,第一个元素的地址为loc(a1),则可以通过(tnggu)如下公式计算出第i个元素的地址loc(a-i):lo

8、c(ai)=loc(a1)+(i-1)k其中loc(a-1)称为基地址。第11页/共101页第十二页,共101页。图2.2 顺序(shnx)表存储示意图 第12页/共101页第十三页,共101页。顺序存储结构可以借助于高级程序设计(chn x sh j)语言中的一堆数组来表示,一维数组的下标与元素在线性表中的序号相对应。线性表的顺序存储结构可用C语言定义如下:define MAXSIZE=线性表可能达到(d do)的最大长度typedef struct ElemType elemMAXSIZE;/*线性表占用的数组空间*/int last;/*记录线性表中最后一个元素在数组elem 中 的位置

9、(下标值),空表置为-1*/SeqList;第13页/共101页第十四页,共101页。2.2.2 线性表顺序存储结构上的基本(jbn)运算 1.查找操作 线性表有两种基本的查找运算(yn sun)。按序号查找GetData(L,i):要求查找线性表L中第i个数据元素,其结果是L.elemi-1或L-elemi-1。按内容查找Locate(L,e):要求查找线性表L中与给定值e相等的数据元素,其结果是:若在表L中找到与e相等的元素,则返回该元素在表中的序号;若找不到,则返回一个“空序号”,如-1。查找运算(yn sun)可采用顺序查找法实现,即从第一个元素开始,依次将表中元素与e相比较,若相等,

10、则查找成功,返回该元素在表中的序号;若e与表中的所有元素都不相等,则查找失败,返回“-1”。第14页/共101页第十五页,共101页。算法(sun f)描述:int Locate(SeqList L,ElemType e)/*在顺序表L中依次存放着线性表中的元素,在表中查找与e相等的元素,若 Li=e,则找到该元素,并返回i值,若找不到,则返回“-1”*/i=0;/*i为扫描计数器,初值为0,即从第一个元素开始比较*/while(i=L.last)&(L.elemi!=e)/*顺序扫描表,直到找到值为key的元素,i+;或扫描到表尾而没找到*/if (ilast+1,i的合法取值范围是 1iL

11、-last+2 */int k;if(iL-last+2)/*首先判断插入位置是否合法*/printf(插入位置i值不合法);return(ERROR);第18页/共101页第十九页,共101页。if(L-last=maxsize-1)printf(表已满无法插入);return(ERROR);for(k=L-last;k=i-1;k-)/*为插入元素(yun s)而移动位置*/L-elemk+1=L-elemk;L-elemi-1=e;/*在C语言数组中,第i个元素(yun s)的下标为i-1*/L-last+;return(OK);第19页/共101页第二十页,共101页。【算法2.2 线

12、性表的插入(ch r)运算】可以看出,当i=L-last+2时,语句L-elemk+1=L-elemk将不会执行,因为循环的终值大于初值,此时不需要移动元素,可直接在表尾插入e。当i=1时,语句L-elemk+1=L-elemk需执行n次,即将表中已存在的n个元素依次后移一个位置(wi zhi)才能将e插入。因此,语句L-elemk+1=L-elemk的频度与插入位置(wi zhi)i有关。第20页/共101页第二十一页,共101页。3.删除操作 线性表的删除运算是指将表的第i(1in)个元素删去,使长度为n的线性表(e1,,ei-1,ei,ei+1,en)变成长度为n-1的线性表(e1,,e

13、i-1,ei+1,en)。例如:线性表(4,9,15,21,28,30,30,42,51,62)删除第5个元素,则需将第6个元素到第10个元素依次向前(xin qin)移动一个位置,如图2.4所示。第21页/共101页第二十二页,共101页。图2.4 顺序(shnx)表中删除元素 第22页/共101页第二十三页,共101页。算法(sun f)描述:int DelList(SeqList*L,int i,ElemType*e)/*在顺序(shnx)表L中删除第i个数据元素,并用指针参数e返回其值。i的合法取值为1iL.last+1*/int k;if(iL-last+1)printf(删除位置不

14、合法!);return(ERROR);第23页/共101页第二十四页,共101页。*e=L-elemi-1;/*将删除的元素存放到e所指向的变量(binling)中*/for(k=i;ilast;k+)L-elemk-1=L-elemk;/*将后面的元素依次前移*/L-last-;Return(OK);第24页/共101页第二十五页,共101页。【算法(sun f)2.3 线性表的删除运算】与插入运算类似,在顺序表上实现删除运算也必须移动结点,这样才能反映出结点间的逻辑关系的变化。若i=L-last+1,则移位语句L-elemk-1=L-elemk不执行,因为循环变量的初值大于终值,此时不需要

15、移动元素,仅将表长度减1即可。显然,删除算法中移位语句L-elemk-1=L-elemk的执行频度(pn d)也与删除位置i有关。第25页/共101页第二十六页,共101页。在顺序表中插入或删除一个数据元素(yun s)时,其时间主要耗费在移动数据元素(yun s)上。对于插入算法而言,设Pi为在第i个元素(yun s)之前插入元素(yun s)的概率,并假设在任何位置上插入的概率相等,即Pi=1/(n+1),i=1,2,,n+1。设Eins为在长度为n的表中插入一元素(yun s)所需移动元素(yun s)的平均次数,则 同理,设Qi为删除第i个元素的概率,并假设(jish)在任何位置上删除

16、的概率相等,即Q i=1/n,i=1,2,,n。删除一个元素所需移动元素的平均次数Edel为 第26页/共101页第二十七页,共101页。例2-1 有两个顺序表LA和LB,其元素均为非递减有序排列,编写一个(y)算法,将它们合并成一个(y)顺序表LC,要求LC也是非递减有序排列。例如LA=(2,2,3),LB=(1,3,3,4),则LC=(1,2,2,3,3,3,4)。算法思想:设表LC是一个空表,为使LC也是非递减有序排列,可设两个指针i、j分别指向表LA和LB中的元素,若LA.elemiLB.elemj,则当前先将LB.elemj插入到表LC中;若LA.elemiLB.elem j,则当前

17、先将LA.elemi插入到表LC中,如此进行下去,直到其中一个表被扫描完毕,然后再将未扫描完的表中剩余(shngy)的所有元素放到表LC中。第27页/共101页第二十八页,共101页。void merge(SeqList*LA,SeqList*LB,SeqList*LC)int i,j,k,l;i=0;j=0;k=0;while(ilast&jlast)if(LA-elemielemj)LC-elemk=LA-elemi;i+;k+;else 第28页/共101页第二十九页,共101页。LC-elemk=LB-elemj;j+;k+;while(ilast)/*当表LA比表LB长时,则将表LA

18、余下(yxi)的元素赋给表LC*/LC-elemk=LA-elemi;i+;k+;while(jlast)/*当表LB比表LA长时,则将表LB余下(yxi)的元素赋给表LC*/LC-elemk=LB-elemj;j+;k+;LC-last=LA-last+LB-last;第29页/共101页第三十页,共101页。【算法2.4 线性表的合并(hbng)运算】由上面的讨论可知,线性表顺序表示的优点是:(1)无需为表示结点间的逻辑关系而增加额外的存储空间(因为逻辑上相邻的元素其存储的物理位置也是相邻的);(2)可方便地随机存取表中的任一元素。其缺点是:(1)插入或删除运算不方便,除表尾的位置外,在表

19、的其它位置上进行插入或删除操作都必须移动大量的结点,其效率较低;(2)由于(yuy)顺序表要求占用连续的存储空间,存储分配只能预先进行静态分配,因此当表长变化较大时,难以确定合适的存储规模。若按可能达到的最大长度预先分配表空间,则可能造成一部分空间长期闲置而得不到充分利用;若事先对表长估计不足,则插入操作可能使表长超过预先分配的空间而造成溢出。第30页/共101页第三十一页,共101页。2.3 线性表的链式存储(cn ch)2.3.1 单链表 图2.5 单链表的结点(ji din)结构 第31页/共101页第三十二页,共101页。单链表包括两个域:数据域用来存储结点的值;指针域用来存储数据元素

20、的直接后继的地址(或位置)。链表正是通过(tnggu)每个结点的指针域将线性表的n个结点按其逻辑顺序链接在一起。由于链表的每个结点只有一个指针域,故将这种链表又称为单链表。由于单链表中每个结点的存储地址是存放在其前趋结点的指针域中的,而第一个结点无前趋,因而应设一个头指针H指向第一个结点。同时,由于表中最后一个结点没有直接后继,则指定线性表中最后一个结点的指针域为“空”(NULL)。这样对于整个链表的存取必须从头指针开始。第32页/共101页第三十三页,共101页。例如:图2.6所示为线性表(A,B,C,D,E,F,G,H)的单链表存储结构,整个链表的存取需从头指针(zhzhn)开始进行,依次

21、顺着每个结点的指针(zhzhn)域找到线性表的各个元素。图2.6 单链表的示例(shl)图 第33页/共101页第三十四页,共101页。图2.7 单链表的逻辑(lu j)状态 图2.8 带头(di tu)结点单链表图示 第34页/共101页第三十五页,共101页。单链表可以由头指针唯一(wi y)确定。单链表的存储结构描述如下:typedef struct Node /*结点类型定义*/ElemType data;struct Node *next;Node,*LinkList;/*LinkList为结构指针(zhzhn)类型*/假设L是LinkList型的变量,则L是一个结构指针,即单链表的

22、头指针,它指向表中第一个结点(对于带头结点的单链表,则指向单链表的头结点),若L=NULL(对于带头结点的单链表为L-next=NULL),则表示单链表为一个空表,其长度为0。若不是空表,则可以(ky)通过头指针访问表中结点,找到要访问的所有结点的数据信息。对于带头结点的单链表L,p=L-next指向表中的第一个结点a1,即p-data=a1,而p-next-data=a2。其余依此类推。第35页/共101页第三十六页,共101页。2.3.2 单链表上的基本(jbn)运算 1.建立(jinl)单链表图2.9 头插法建立(jinl)单链表图示 第36页/共101页第三十七页,共101页。用头插法

23、建立(jinl)单链表的算法:Linklist CreateFromHead()LinkList L;Node *s;char c;int flag=1;/*设置(shzh)一个标志变量flag,初值为1,当输入“$”时,将flag置为0,建表结束*/L=(Linklist)malloc(sizeof(Node);/*为头结点分配存储空间*/L-next=NULL;While(flag)第37页/共101页第三十八页,共101页。c=getchar();if(c!=$)s=(Node*)malloc(sizeof(Node);/*为读入的字符(z f)分配存储空间*/s-data=c;s-ne

24、xt=L-next;L-next=s;else flag=0;return L;=第38页/共101页第三十九页,共101页。【算法(sun f)2.5 用头插法建立单链表】2)尾插法建表 图2.10 尾插法建表图示 第39页/共101页第四十页,共101页。该算法的实现与头插法建表的不同之处在于指针的变化(binhu),其具体实现如下:Linklist CreateFromTail()/*将新增的字符追加(zhuji)到链表的末尾*/LinkList L;Node*r,*s;int flag=1;/*设置一个标志,初值为1,当输入“$”时,flag为0,建表结束*/L=(Node*)mall

25、oc(sizeof(Node);/*为头结点分配存储空间*/L-next=NULL;r=L;/*r指针始终动态指向链表的当前表尾,以便于做尾插入,其初值指向头结点*/while(flag)第40页/共101页第四十一页,共101页。c=getchar();if(c!=$)s=(Node*)malloc(sizeof(Node);s-data=c;r-next=s;r=s;else flag=0;r-next=NULL;/*将最后一个结点的next链域置为空,表示(biosh)链表 的结束*/*while*/return L;/*CreateFromTail*/第41页/共101页第四十二页,共

26、101页。【算法(sun f)2.6 尾插法建表】2.查找 1)按序号查找 在单链表中,由于每个结点的存储位置(wi zhi)都放在其前一结点的next域中,因而即使知道被访问结点的序号i,也不能像顺序表那样直接按序号i访问一维数组中的相应元素,实现随机存取,而只能从链表的头指针出发,顺链域next逐个结点往下搜索,直至搜索到第i个结点为止。第42页/共101页第四十三页,共101页。算法描述:设带头结点的单链表的长度为n,要查找表中第i个结点,则需要从单链表的头指针L出发,从头结点(L-next)开始顺着链域扫描(somio),用指针p指向当前扫描(somio)到的结点,初值指向头结点,用j

27、做计数器,累计当前扫描(somio)过的结点数(初值为0),当j=i 时,指针p所指的结点就是要找的第i个结点。第43页/共101页第四十四页,共101页。Node*Get(LinkList L,int i)/*在带头结点的单链表L中查找第i个结点,若找到(1in),则返回(fnhu)该结点的存储位置;*/*否则返回(fnhu)NULL*/int j;Node *p;p=L;j=0;/*从头结点开始扫描*/while(p-next!=NULL&jnext;/*扫描下一结点*/j+;/*已扫描结点计数器*/if(i=j)return p;/*找到了第i个结点*/else return NULL;

28、/*找不到,i0或in*/*Get*/第44页/共101页第四十五页,共101页。【算法2.7 在单链表L中查找(ch zho)第i个结点】2)按值查找 算法描述:按值查找是指在单链表中查找是否有结点值等于e的结点,若有的话,则返回首次找到的其值为e的结点的存储(cn ch)位置,否则返回NULL。查找过程从单链表的头指针指向的头结点出发,顺着链逐个将结点的值和给定值e作比较。第45页/共101页第四十六页,共101页。Node*Locate(LinkList L,ElemType key)/*在带头(di tu)结点的单链表L中查找其结点值等于key的结点,若找到则返回该结点的位置p;否则返

29、回NULL*/Node*p;p=L-next;/*从表中第一个结点比较*/while(p!KG-*2=NULL)if(p-data!KG-*2=key)p=p-next;else break;/*找到结点key,退出循环*/return p;/*Locate*/第46页/共101页第四十七页,共101页。【算法(sun f)2.8 在单链表L中查找值等于key的结点】3.单链表插入操作 算法描述:要在带头结点的单链表L中第i个位置插入一个数据元素e,需要首先在单链表中找到第i-1个结点并由指针pre指示(zhsh),然后申请一个新的结点并由指针s指示(zhsh),其数据域的值为e,并修改第i-

30、1个结点的指针使其指向s,然后使s结点的指针域指向原第i个结点。插入结点的过程如图2.11所示。第47页/共101页第四十八页,共101页。int InsList(LinkList L,int i,ElemType e)/*在带头结点的单链表L中第i个位置(wi zhi)插入值为e的新结点 */Node*pre,*s;int k;pre=L;k=0;while(pre!KG-*2=NULL&knext;k=k+1;第48页/共101页第四十九页,共101页。if(k!=i-1)/*即while循环是因为pre=NULL或idata=e;/*将待插入结点的值e赋给s的数据域*/s-next=pr

31、e-next;/*完成插入操作*/pre-next=s;return OK;第49页/共101页第五十页,共101页。【算法2.9 单链表插入(ch r)操作】图2.11 在单链表第i个结点前插入(ch r)一个结点的过程 第50页/共101页第五十一页,共101页。4.删除(shnch)图2.12 单链表的删除(shnch)过程 第51页/共101页第五十二页,共101页。int DelList(LinkList L,int i,ElemType*e)/*在带头结点的单链表L中删除第i个元素,并将删除的元素保存到变量(binling)*e中*/Node*p,*r;int k;p=L;k=0;

32、while(p-next!KG-*2=NULL&knext;k=k+1;ZK)第52页/共101页第五十三页,共101页。if(k!=i-1)/*即while循环是因为p-next=NULL或inext;p-next=p-next-next;/*删除结点r*/free(r);/*释放被删除的结点所占的内存空间*/return OK;第53页/共101页第五十四页,共101页。【算法2.10 单链表删除(shnch)操作】说明:删除算法中的循环条件(p-next!=NULL&ki-1)与前插算法中的循环条件(p!=NULL&knext=NULL)。int ListLength(LinkList

33、L)/*本算法用来求带头结点(ji din)的单链表L的长度*/Node*p;p=L-next;j=0;/*用来存放单链表的长度*/while(p!KG-*2=NULL)p=p-next;j+;return j;/*End of function ListLength*/第55页/共101页第五十六页,共101页。【算法(sun f)2.11 求单链表的长度】例2-3 如果以单链表表示集合,假设集合A用单链表LA表示,集合B用单链表LB表示,设计算法求两个集合的差,即A-B。算法思想:由集合运算的规则可知(k zh),集合的差A-B中包含所有属于集合A而不属于集合B的元素。具体做法是,对于集合

34、A中的每个元素e,在集合B的链表LB中进行查找,若存在与e相同的元素,则从LA中将其删除。第56页/共101页第五十七页,共101页。void Difference(LinkList LA,LinkList LB)/*此算法求两个集合的差集*/Node *pre;*p,*r;pre=LA;p=LA-next;/*p指向LA表中的某一结点,而pre始终(shzhng)指向p 的前驱*/while(p!=NULL)q=LB-next;/*依次扫描LB中的结点,看是否有与LA中*p结点的值相同的结点*/while(q!=NULL&q-data!=p-data)q=q-next;if(q!KG-*2=

35、NULL)第57页/共101页第五十八页,共101页。r=p;pre-next=p-next;p=p-next;free(r);else pre=p;p=p-next;/*while(p!=NULL)*/第58页/共101页第五十九页,共101页。【算法(sun f)2.12 用单链表求两个集合的差集】2.3.3 循环(xnhun)链表 循环链表(Circular Linked List)是单链表的另一种形式,它是一个首尾相接的链表。其特点是将单链表最后一个结点(ji din)的指针域由NULL改为指向头结点(ji din)或线性表中的第一个结点(ji din),就得到了单链形式的循环链表,并

36、称为循环单链表。类似地,还有多重链的循环链表。在循环单链表中,表中所有结点(ji din)都被链在一个环上,多重循环链表则是将表中的结点(ji din)链在多个环上。为了使某些操作实现起来方便,在循环单链表中也可设置一个头结点(ji din)。这样,空循环链表仅由一个自成循环的头结点(ji din)表示。第59页/共101页第六十页,共101页。图2.13 带头结点(ji din)循环单链表 第60页/共101页第六十一页,共101页。例2-4 有两个带头结点的循环(xnhun)单链表LA、LB,编写一个算法,将两个循环(xnhun)单链表合并为一个循环(xnhun)单链表,其头指针为LA。算

37、法思想:先找到两个链表的尾,并分别由指针p、q指向它们,然后将第一个链表的尾与第二个表的第一个结点链接起来,并修改第二个表的尾Q,使它的链域指向第一个表的头结点。第61页/共101页第六十二页,共101页。LinkList merge-1(LinkList LA,LinkList LB)/*此算法将两个链表的首尾连接起来*/Node*p,*q;p=LA;q=LB;while(p-next!=LA)p=p-next;/*找到表LA的表尾,用p指向它*/while(q-next!=LB)q=q-next;/*找到表LB的表尾,用q指向它*/q-next=LA;/*修改(xigi)表LB 的尾指针,

38、使之指向表LA 的头结点*/p-next=LB-next;/*修改(xigi)表LA的尾指针,使之指向表LB 中的第一个结点*/free(LB);return(LA);第62页/共101页第六十三页,共101页。【算法(sun f)2.13 循环单链表的合并算法(sun f)(1)】采用上面(shng min)的方法,需要遍历链表,找到表尾,其执行时间是O(n)。若在尾指针表示的单循环链表上实现,则只需要修改指针,无需遍历,其执行时间是 O(1)。LinkList merge-2(LinkList RA,LinkList RB)/*此算法(sun f)将两个链表首尾连接起来*/Node*p;p

39、=RA-next;/*保存链表RA的头结点地址*/RA-next=RB-next-next;/*链表RB的开始结点链到链表RA的终端结点之后*/free(RB-next);/*释放链表RB的头结点*/RB-next=p;/*链表RA的头结点链到链表RB的终端结点之后*/return RB;/*返回新循环链表的尾指针*/第63页/共101页第六十四页,共101页。【算法2.14 循环(xnhun)单链表的合并算法(2)】2.3.4 双向链表 循环单链表的出现,虽然能够实现从任一结点出发沿着链能找到其前驱结点,但时间耗费是O(n)。如果希望从表中快速确定某一个(y)结点的前驱,另一个(y)解决方法

40、就是在单链表的每个结点里再增加一个(y)指向其前驱的指针域prior。这样形成的链表中就有两条方向不同的链,我们可称之为双(向)链表(Double Linked List)。双链表的结构定义如下 typedef struct DNode ElemType data;struct DNode*prior,*next;DNode,*DoubleList;第64页/共101页第六十五页,共101页。图2.14 双链表的结点(ji din)结构 第65页/共101页第六十六页,共101页。由于在双向链表中既有前向链又有后向链,寻找任一个结点的直接前驱结点与直接后继结点变得非常方便。设指针(zhzhn)

41、p指向双链表中某一结点,则有下式成立:p-prior-next=p=p-next-prior 第66页/共101页第六十七页,共101页。图2.15 双向循环(xnhun)链表图示 第67页/共101页第六十八页,共101页。1.双向链表的前插操作(cozu)图2.16 双向链表插入(ch r)操作 第68页/共101页第六十九页,共101页。int DlinkIns(DoubleList L,int i,ElemType e)DNode *s,*p;./*先检查待插入的位置i是否合法(实现(shxin)方法同单链表的前插操作)*/./*若位置i合法,则让指针p指向它*/s=(DNode*)m

42、alloc(sizeof(DNode);if(s)s-data=e;s-prior=p-prior;p-prior-next=s;s-next=p;p-prior=s;return TRUE;else return FALSE;第69页/共101页第七十页,共101页。【算法(sun f)2.15 双向链表的插入操作】2.双向链表的删除操作(cozu)算法描述:图2.17 双向链表的删除(shnch)操作 第70页/共101页第七十一页,共101页。int DlinkDel(DoubleList L,int i,ElemType*e)DNode *p;./*首先检查待插入的位置i是否合法(hf

43、)(实现方法同单链表的删除 操作)*/./*若位置i合法(hf),则让指针p指向它*/*e=p-data;p-prior-next=p-next;p-next-prior=p-prior;free(p);return TRUE;第71页/共101页第七十二页,共101页。【算法2.16 双向链表的删除(shnch)操作】例2-5 设一个循环双链表L=(a,b,c,d),编写一个算法,将链表转换为L=(b,a,c,d)。算法思想:本题实际上是交换(jiohun)表中前两个元素的次序。第72页/共101页第七十三页,共101页。void swap(DLinkList L)DNode *p,*q,*

44、h;h=L-next;/*h指向表中的第一个结点(ji din),即a*/p=h-next;/*p指向b结点(ji din)*/q=h-prior;/*保存a 结点(ji din)的前驱*/h-next=p-next;/*a结点(ji din)的后继指向c结点(ji din)*/p-next-prior=h;/*c结点(ji din)的前驱指向a结点(ji din)*/p-prior=q;/*将b结点(ji din)插入,作为表的第一个结点(ji din)*/p-next=h;L-next=p;/*将表的头结点(ji din)的next 域指向b结点(ji din)*/第73页/共101页第七

45、十四页,共101页。【算法2.17 交换循环双链表中前两个元素(yun s)的次序】*2.3.5 静态(jngti)链表 静态链表同样可以借助一维数组来描述:define Maxsize=链表可能(knng)达到的最大长度typedef struct ElemType data;int cursor;Component,StaticListMaxsize;第74页/共101页第七十五页,共101页。图2.18 静态链表的插入和删除(shnch)操作示例 第75页/共101页第七十六页,共101页。1.初始化 所谓初始化操作(cozu),是指将这个静态单链表初始化为一个备用静态单链表。设spac

46、e为静态单链表的名字,av为备用单链表的头指针,其算法如下:void initial(StaticList space,int*av)int k;space0-cursor=0;/*设置已用静态单链表的头指针指向位置0*/for(k=0;kcursor=k+1;/*连链*/spaceMaxsize-1=0;/*标记(bioj)链尾*/*av=1;/*设置备用链表头指针初值*/第76页/共101页第七十七页,共101页。【算法(sun f)2.18 静态单链表初始化】2.分配结点int getnode(int*av)/*从备用链表摘下一个结点空间(kngjin),分配给待插入静态链表中的元素*/

47、int i;i=*av;*av=space*av.cur;return i;第77页/共101页第七十八页,共101页。【算法2.19 分配(fnpi)结点】3.结点回收(hushu)void freenode(int*av,int k)/*将下标为 k的空闲结点插入到备用链表*/spacek.cursor=*av;*av=k;第78页/共101页第七十九页,共101页。【算法(sun f)2.20 空闲结点回收】4.前插操作 在已用静态(jngti)单链表space的第i个数据元素之前插入一个数据元素x。算法描述:先从备用单链表上取一个可用的结点;将其插入到已用静态(jngti)单链表第i个

48、元素之前。第79页/共101页第八十页,共101页。void insbefore(StaticList space,int i,int*av)int j,k,m;j=*av;/*j为从备用表中取到的可用结点空间的下标(xi bio)*/av=spaceav-cursor;/*修改备用表的头指针*/spacej-data=x;k=space0-cursor;/*k 为已用静态单链表的第一个元素的下标(xi bio)值*/for(ZK(m=1;mcursor;spacej-cursor=spacek-cursor;/*修改游标域,实现插入操作*/spacek-cursor=j;第80页/共101页

49、第八十一页,共101页。【算法(sun f)2.21 在已用静态单链表的第i个元素之前插入元素x】5.删除 删除已用静态单链表中第i个元素。算法描述:寻找第i-1个元素的位置,然后通过修改相应的游标域进行删除;将被删除的结点(ji din)空间链到可用静态单链表中,实现回收。第81页/共101页第八十二页,共101页。void delete(StaticList space;int i;int*av )int j,k,m;k=space0-cursor;for(m=1,mcursor;j=spacek-cursor;spacek-cursor=spacej-cursor;/*从已用表中删除第i

50、 个 元素(yun s)*/spacej-cursor=*av;/*将第i 个元素(yun s)占据的空间回收,即将其链 入备用表*/av=j;/*置备用表头指针以新值*/第82页/共101页第八十三页,共101页。【算法(sun f)2.22 删除已用静态单链表中的第i个元素】2.3.6 顺序(shnx)表和链表的比较 1.基于空间(kngjin)的考虑 在链表中的每个结点,除了数据域外,还要额外设置指针(或光标)域,从存储密度来讲,这是不经济的。所谓存储密度(Storage Density),是指结点数据本身所占的存储量和整个结点结构所占的存储量之比,即 存储密度=结点数据本身所占的存储量

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 管理文献 > 管理工具

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁