1、第二章 基本数据结构及其运算,2.1 数据结构的基本概念2.2 线性表及顺序存储结构2.3 线性表链表及其运算2.4 数组2.5 树与二叉树2.6 图,本章主要介绍:数据结构、数据逻辑结构、数据存储结构的基本概念;几种常用的数据结构(线性表、栈、队列、数组、树与二叉树、图),阐明这些数据结构内在的逻辑关系,讨论它们在计算机中存储的常用方式:顺序存储和链式存储,以及在这些数据结构上进行各种运算的算法。 重点:理解数据结构、数据逻辑结构和存储结构的概念,掌握常用的数据结构中各数据内在的逻辑关系,在计算机中的存储方式,以及在其上进行各种运算的算法。 难点:正确区分数据逻辑结构和存储结构,掌握常用数据
2、结构在计算机中的存储方式,及在其上进行各种运算的算法。,1、数据元素之间的固有逻辑关系,称为数据的逻辑结构,数据结构主要研究和讨论三方面问题:,2、数据元素及其关系在计算机中的存储方式,称为数据的物理结构或存储结构,3、施加在数据结构上的操作,称为数据结构的运算。数据处理的本质就是对数据结构施加各种运算,常见的运算有:查找、排序、插入、删除等。,2.1 数据结构的基本概念,例1、无序表的顺序查找与有序表的对分查找。,2.1.1 两个例子,2、尽量节省数据处理过程中所占用的存储空间,1、提高数据处理的速度,主要目的是提高数据处理的效率:,1 2 3 4 5 6 7 8 9 10,1 2 3 4
3、5 6 7 8 9 10,data0 data1 data2 data3 data4 data5 data6 data7 data8,13 24 42 77,28 30,12132124,28 30 42 77,25,(a)无序表,data0 data1 data2 data3 data4 data5 data6 data7 data8,21,12,25,(b)有序表,图2.1 数据元素存放顺序不同的两个表,表(a)只能采用顺序查找,将x与表中每一个元素进行比较,查找效率较低。,因表(b)中的元素是有序排列,可找到其中间元素data4,将x与它进行比较,有三种可能:x=data4xdata4x
4、data4,找到,抛弃表的前半部分,在表的后半部分用相同的方法继续查找,抛弃表的后半部分,在表的前半部分用相同的方法继续查找,用这种方法查找,每次比较都可抛弃子表一半的元素,查找效率较高,从该例可看出,数据元素在表中的排列顺序对查 找效率有很大的影响,例2、学生情况登记表信息查询,从该例可看出,在对数据进行处理时,可根据所做的运算不同,将数据组织成不同的形式,也可提高数据处理的效率,2.1.2 什么是数据结构,数据结构:互相有关联的数据元素的集合。,例:向量和矩阵就是数据结构,在这两个数据结构中,数据元素之间有位置上的关系,数据:反映客观事物信息集合,在现实生活中称信息在计算机中称数据;即数据
5、是符号化的信息。它由数据元素组成,数据元素(元素):数据集合中的一个元素,是数据的基本单位。,数据元素具有广泛的含义,现实世界中的一切个体可以是数据元素,例:描述四季的季节名春、夏、秋、冬可以作为季节(数据)的数据元素,描述学生特征的信息:(970158、赵凯、男、1970、70),(970159、李启明、男、21、91),(970162、张军、 男、18、80)可以作为学生情况登记表(数据)的数据元素,甚至每一个客观存在的事件:如一次借书、一次比赛等也可作为数据元素,总之,在数据处理领域,每一个需要处理的对象都可抽象成数据元素,要表示一个数据结构,需表示出:,1、数据元素的集合,记为D,2、
6、在D中各数据元素之间的关系,记为R,则:数据结构 B = ( D , R ),在数据处理领域,数据元素之间的任何关系都可以用前后件关系描述,例1:春、夏、秋、冬四季,春是夏的前件,夏是春的后件,为反映春、夏、秋、冬这四个元素之间的前后件关系,一般采用二元组表示,也称二元关系(春,夏)、(夏,秋)、(秋,冬),故:一年四季的数据结构可表示为,D =,春,夏,秋,冬,R =,(春,夏),(夏,秋),(秋,冬),B = ( D , R ),例2、n维向量X=(x1,x2, xn)是一个数据结构,它可表示为:,D =,x1,x2,xn,R =,(x1,x2) , (x2,x3) , , (xn-1,x
7、n),B = ( D , R ),对于复杂的数据结构,它的数据元素可以是另一种数据结构。,它的每一行Ai= (ai1,ai2,ain) i=1,2,m 可以看成是它的一个数据元素, D=A1,A2,Am D上的关系为:R=(A1,A2),(A2,A3),(Am-1,Am),例:mn的矩阵,是一个数据结构,显然,数据结构A中的每一个元素Ai (i=1,2,m)又是另一个数据结构,其数据元素, Di=ai1,ai2,aim Di上的关系为:Ri=(ai1,ai2),(ai2,ai3),(aim-1,aim),可看出:, 、数据的逻辑结构在计算机存储器中的存储方式称为数据的物理结构(存储结构)。,
8、、要将一个数据存储在计算机中应存储:,数据元素的集合D,数据元素之间的关系R, 、一个数据结构中的关系R,实际上是D上各数据元素之间的联系,并不表示数据在计算机中的存储位置,称为数据的逻辑结构。,综上,数据的逻辑结构是数据本身所固有的,而存储结构则可根据运算需要进行设计或构造(即一个逻辑结构可表示成多种存储结构)。在进行数据处理时,应根据需要处理的不同,采取不同的存储结构,以提高处理效率。,D中的数据元素用中间标有元素值的方框表示,称为数据结点(结点);R中的关系用一条有向线段从前件结点指向后件结点。,2.1.3 数据结构的图形表示,例:设数据元素的集合为D = di |1 i 7的整数,画出
9、对应于下列关系所构成的数据结构的图形 、R1=(d1,d3),(d1,d7),(d4,d5),(d3,d6),(d2,d4) 、R2=(di,dj)|i+j=5 、R3=(d2,d3)(d3,d1),(d1,d4),(d4,d6),d6,d5),(d5,d7),( D , R3 ),( D , R1 ),( D , R2 ),没有前件的结点称为根结点,没有后件的结点称为终端结点(叶子结点),其余的结点称为内部结点,线性结构:一个非空数据结构满足下列三个条件,则称该数据结构为线性结构: 、有且仅有一个根结点 、每个结点最多只有一个前件,也最多有一个后件 、插入和 删除结点后仍满足、,线性结构:从
10、根结点到终结点之间只有一条由有向线段连起的路径,2.1.4 线性数据结构与非线性数据结构,数据的逻辑结构可分为两大类,线性结构,非线性结构,不是线性结构,非线性结构:不满足线性结构特点的数据结构,即该结构中结点可能有多个前件和多个后件。典型的非线性结构为图结构,树是一种特殊的非线性结构。,树结构,图结构,2.2 线性表及其顺序结构,2.2.1 线性表及其运算,1、什么是线性表 线性表是由n(n0)个具有相同类型的数据元素 a1,a2,ai,an 组成的一个有限序列。表中的每一个数据元素,除了第一个外,有且只有一个前件;除了最后一个外,有且只有一个后件。其中 n 为表长(n=0时为空表),ai为
11、线性表中的第i个元素, ai 可以是一个数,符号或其它更复杂的信息。,其数据结构表示为:D =a1,a2 ,an R =(a1,a2) ,(a2 ,a3),(an-1, an),图形表示为:,线性表是一种线性结构。,逻辑结构,例1:一个n维向量:X=(x1,x2, xn)为一个线性表英语小写字母表(a,b,c,z)也是一个线性表,例2:某班学生情况登记表,是比较复杂的线性表,2、线性表的顺序存储结构,数据的逻辑结构在计算机存储器中的存储方式称为数据的存储结构,数据的存储结构是指:,根据存储关系R的方式不同,存储结构分为两种: 、顺序存储结构 、链式存储结构,、如何为数据元素分配存储单元,、如何
12、实现数据元素之间的关系,顺序存储结构是将(D , R)中逻辑上相邻的数据元素存储在物理上相邻的存储单元中,而数据元素之间关系由存储单元的邻接关系唯一确定,例:D=a,b,c,d,e,f, R=(b,c),(c,d),(d,a),(a,f),(f,e),逻辑结构,存储结构,( D , R ),可看出:,、顺序存储结构主要用于存储线性结构,而存储非线性结构较困难,、顺序存储结构必须要有一片连续空间存储数据元素,结构中各元素按它们之间的关系顺序存放,将线性表的顺序存储结构称为顺序表。 注意:线性表与顺序表的区别,数据逻辑结构,数据存储结构,编程时,可用一维数组或用一组地址连续的存储单元来依次存储线性
13、表中的数据元素。,、用数组v(1:m),构成可存储m个数据元素的线性表,v(1)=b,v(2)=c,v(3)=d,v(4)=a,v(5)=f, v(6)=e, 表长n=6,、用C动态分配内存地址函数malloc或C+运算符new构成可存储m个数据元素的线性表,#include “stdlib.h” void initsl(ET *v,int m,int* n) v=(ET*)malloc(m*sizeof(ET); /.C程序或 v=new ETm /.CPP程序v0=b;v1=c;v2=d;v3=a;v4=f; v5=e;*n=6; /其中ET表示线性表中元素的数据类型,m表长,在顺序表中,
14、设线性表中每一个数据元素占用k个存储单元,线性表中任一元素ai的存储地址可用下式来表示:,ADR(ai) = ADR(a1) + (i-1)*k,在顺序表中读取任何一个元素所用时间相同,读取元素方便,也称为随机存储结构,线性表可进行主要运算:,、在线性表指定位置加入一个新元素(线性表插入),、在线性表中删除指定元素(线性表删除),、在线性表中查找某个特定的元素(线性表查找),、对线性表中元素进行排序(线性表排序),、将一个线性表分解成多个线性表(线性表分解),、将多个线性表合并成一个线性表(线性表合并),、复制一个线性表(线性表复制),、逆转一个线性表(线性表逆转),注意:运算定义在逻辑结构上
15、,在不同存储结构下有不同的实现方法(算法),3、线性表在顺序存储下的插入运算,1 2i-1 i i+1n n+1,1 2i-1 in,b,a1a2 ai-1,ai an-1an,b,V1 V2Vi-1 ViVn,V1 V2Vi-1 Vi Vi+1Vn Vn+1,该算法涉及到的输入、输出数据:,异常情况分析,主要分析: 、现在所拥有的条件能否让算法顺利执行完成 、根据算法特征第四条,要求正确的输入信息,对本算法,其异常情况为:,、表满时,不能插入,、插入点不在表中,n=m,in,i1,设插在表尾,即i=n+1,设插在表头,即i=1,要判断异常情况,需用到数据m,必须输入m,故:该算法应输入、输出
16、的数据为:,v,b,i,n,m,v,n,PROCEDURE INSL(v , m , n , b , i)IF (n=m) THEN overflow ; RETURNIF (in) THEN i=n+1IF (i1) THEN i=1FOR j=n TO i BY 1 DO V(j+1)=V(j) V(i)=b 或 V(j+1)=bn=n+1RETURN,其算法为:,设长度为n的线性表为(a1,a2,ai-1, ai ,ai+1, ,an),删除 第i个元素,删除后的线性表为(a1,a2, ,ai-1,ai+1 , ,an )。,3、线性表在顺序存储下的删除运算,1 2i-1 in-1,1
17、2i-1 in,a1a2 ai-1ai+1, an,V1 V2Vi-1 ViVn,V1 V2Vi-1 ViVn-1,该算法涉及到的输入、输出数据:,异常情况为:,、表空时,不能删除,、删除点超出表范围,n=0,in 或 i1 不能进行删除,其算法为:,PROCEDURE DESL(V , n , i)IF (n=0) THEN UNDERFLOW ; RETURN IF (in) THEN printf(“Not this element in the list”; RETURN FOR j=i TO n-1 DO V(j)=V(j+1)n=n-1RETURN,例:C+语言编写顺序表基本操作:
18、表初始化、输出、插入与删除(C+幻灯20),顺序表操作的特点:,1 顺序表中数据元素的个数需要预先确定;,2 由于顺序表的随机存取特性,访问每个元素很方便;,3 插入和删除操作需移动大量的元素, 平均为 个,4、需一片连续空间,线性表容量不易扩充,2.2.2 栈及其应用,例:下列给出了具有嵌套调用的五个程序,1、什么是栈,返回地址:A、B、C、D,A、B、C、D组成一个线性表,计算机系统在处理时可用一个线性表来动态记忆调用过程中的路径,即建立一个空线性表,调用函数时将返回地址插入线性表,返回主程序时将返回地址从表中删除;但如何处理插入与删除的元素,才能让调用过程不出差错。,要让调用过程不出差错
19、,这四个元素的插入顺序必须为A、B、C、D,而删除顺序刚好与这相反,为D、C、B、A,,如规定只能在一端进行插入与删除操作,可满足上述要求。这种只能在一端进行插入与删除操作的线性表称为栈。,允许插入和删除的一端称为栈顶,而不允许插入与删除的一端称为栈底。,入栈顺序:a1,a2,a3,an 出栈顺序:an,an-1,a2,a1 栈的操作原则:先进后出,栈底,栈顶,插入(入栈),删除 (出栈),top,bottom,随着入栈与出栈操作的进行,栈顶的位置浮动变化,为反映这种变化,设置一个栈顶指针top,指向当前栈顶元素的存储位置,设一个栈底指针bottom,指向栈底元素的存储位置。,2、栈的基本运算
20、 (1)入栈:在栈顶端插入一个新元素 (2)出栈(退栈):从栈顶删除一个元素 (3)取栈顶元素:在栈中读栈顶元素,3、栈的顺序存储结构及其运算,栈是一种特殊的线性表,与一般顺序存储结构的线性表一样,也可利用一片连续的存储单元依次存放自栈底到栈顶的数据元素,,可用一维数组S(1:m)模拟栈,m为栈的容量 一般取:bottom=1,入栈:,top=top+1,S(top)=x,出栈:,top=top-1,y=S(top),栈空:,top=0,栈满:,top=m,初始状态:,top=0,算法2.3 在容量为m的栈s中插入一个元素x,PROCEDURE PUSH (S , m , top , x)IF
21、 (top=m) THEN stack-OVERFLOW; RETURN top=top+1S(top)=xRETURN,异常情况为:,栈满时,不能插入,top=m,该算法涉及到的输入、输出数据:,算法2.4 在容量为m的栈s中删除一个元素,PROCEDURE POP(S , top , y)IF ( top=0 ) THEN stack-UNDERFLOW; RETURN y=S(top)top=top-1RETURN,异常情况为:,栈空时,不能删除,top=0,该算法涉及到的输入、输出数据:,算法2.5 读栈顶元素,PROCEDURE TOP (S, top , y)IF (top=0)
22、THEN stack-UNDERFLOW; RETURN y=S(top)RETURN,异常情况为:,栈空时,无元素可读,top=0,该算法涉及到的输入、输出数据:,栈是最广泛使用的数据结构之一,子程序的调用,递归过程的实现,表达式的计算都是栈应用的典型例子。自学P38表达式的计算,2.2.3 队列及其应用,1、什么是队列,队列也是一种特殊的线性表,它只允许在一端进行插入,而在另一端进行删除,允许插入的一端称为队尾,用一个尾指针rear指示,允许删除的一端称为队(排)头,用一个排头指针(front)指示。,入队顺序:A,B,C,D,E,F 出队顺序:A,B,C,D,E,F,队列的操作原则:先进
23、先出,同栈类似,在顺序存储结构下,可用一维数组Q(1:m)模拟队列,m为队列的容量,入队:,rear=rear+1,Q(rear)=x,出队:,y=Q(front),队空:,front=rear,队满:,rear=m,初始状态:,front=rear=0,front=front+1,由于队列只能在一端插入,在另一端删除,随着入队与出队运算不断进行,队列中元素不断向队尾方向移动,而在排头产生一片不能用的空间,最后可能导致尾指针指向队列最后一个位置,而排头却有一片无法利用的空闲区,这种现象称为“假溢出”,front,rear,如何避免“假溢出”现象的发生:,最简单的办法,在进行入队与出队运算时,调
24、整队列中元素在存储空间中的位置,即出队时将队列中所有元素依次向排头方向移动一个位置。但这种办法需移动大量的元素,在实际中一般不用,而是采取另一种办法。,2、循环队列,将队列存储空间的最后一个位置饶到第一个位置,形成逻辑上的环状空间,供队列循环使用,m,1,入队:,rear=rear+1,Q(rear)=x,出队:,y=Q(front),队空:,front=rear,队满:,rear=front,初始状态:,front=rear=m,front=front+1,循环队列的运算,If rear=m+1 Then rear =1,If front=m+1 Then front=1,由此可见,循环队列
25、结构虽然避免了“假溢出”现象,但却带来一个新问题,无法区别满足条件front=rear的队列是处于队空还是队满的状态,为解决这个问题,可采用两种方法:,(1)、另设一个标志以区别队空和队满,队满条件:,s=1 and rear=front,队列初始状态:,s=0 且front=rear=m,队空条件:,s=0,入队操作:,If (rear=front)and(s=1) Then “队满” ;Return rear=rear+1 If rear=m+1 Then rear=1 Q(rear)=x s=1,出队操作:,If (s=0) Then “队空” ;Return front=front+1
26、 If front=m+1 Then front=1 y=Q(front) If rear=front Then s=0,完整的算法见P4344,(2)、用队尾指针追上排头指针这一特征作为队满的条件,入队时,将rear+1=front作为队满的条件,即:rear=rear+1If rear=m+1 Then rear=1If rear=front Then “队满”,队空:rear=front,算法2.6a 在容量为m的循环队列Q中插入一个元素x,PROCEDURE ADDCQ(Q , m , rear , front , x)t=rear+1IF (t=m+1) THEN t=1IF (t=
27、front) THEN “OVERFLOW”; RETURNrear=tQ(rear)=xRETURN,异常情况为:,队满时,不能插入,(rear+1) mod m=front,该算法涉及到的输入、输出数据:,算法2.7a 在容量为m的循环队列Q中删除一个元素,PROCEDURE DELCQ(Q , m , rear , front , y)IF(rear=front) THEN “UNDERFLOW” ; RETURNfront=front+1IF (front=m+1) THEN front=1y=Q(front)RETURN,异常情况为:,队空时,不能删除,rear=front,该算法涉
28、及到的输入、输出数据:,队列在计算机中也有广泛的应用,凡可抽象为线性表并符合先到先服务的处理过程,均可用队列模拟。例VB中的事件队列;计算机中CPU与外设传递数据时,在内存中设置的缓冲区队列。P48介绍了队列在日常生活中应用,自学,线性表顺序存储结构具有结构简单,读取元素方便等优点,适合小线性表或长度固定的线性表,但它存在以下几方面的缺点:, 需一片连续空间,不能利用存储器中的碎片,且线性表容量不易扩充, 不能对存储空间进行动态分配;, 插入和删除操作需移动大量的元素, 平均为 个,对于大的线性表或元素变化频繁的线性表不宜采用顺序结构,而是采用链式存储结构,1、线性链表,线性链表是线性表的链式
29、存储结构,在链式存储结构中,数据元素可存储在不连续的空间中,各数据元素之间的关系不是由存储单元的邻接关系确定,而是由指针域确定。,2.3 线性链表及其运算,2.3.1 线性链表的基本概念,在链式存储结构中,每一个数据元素的表示由两部分信息组成:一是数据元素的值;二是各数据元素的前后件关系,存储数据 元素值,存储与该结点逻辑上 相邻的结点地址,即:线性链表中每一个元素的存储单元都由数据域和指针域两部分组成,称为存储结点(结点),只有一个指针域时,其存储内容为该结点后件的地址,无后件结点,指针域为“0”、“NULL”或“”,例:已知数据结构B=(D,R),D=a,b,c,d,e,f,R=(b,c)
30、,(c,d),(d,a),(a,f),(f,e),其链式存储结构为:,注意: 头指针Head是整个链表的唯一标识,通过它可找到链表中任意元素 数据元素间的逻辑关系是通过指针来反映的 链式结构既可存储线性结构,也可存储非线性结构(多个后件用多个指针域指向,前件也可用指针域指出,线性链表的物理状态,用链式结构存储线性表时,每个结点的存储空间可任意分配,它们可以不连续,它们之间的关系由指针域确定,在程序设计时,可用两个一维数组V(1:m),Next(1:m)存储线性表,用V表示数据,Next表示指针域则第i个结点为,数据元素值,数据元素地址,上例用数组存储: R=(b,c),(c,d),(d,a),
31、(a,f),(f,e),V(1)=a、 V(2)=b、 V(3)=c、 V(4)=d、 V(5)=e、 V(6)=f,Next(1) =,6,Next(2) =,3,Next(3) =,4,Next(4) =,1,Next(5) =,0,Next(6) =,5,Head =,2,通过Head可找到链表中任意元素,例:,V(Head)=V(2)=b p=Next(Head)=Next(2)=3 , V(p)=V(3)=c,一般而言,线性链表(a1, a2, a3, ai, an)可用如下逻辑状态图来表示:,上例可用下图表示线性链表的逻辑状态: V(1)=a、 V(2)=b、 V(3)=c、 V(
32、4)=d、 V(5)=e、 V(6)=f R=(b,c),(c,d),(d,a),(a,f),(f,e),Head,2,3,4,1,6,5,线性链表中的各结点在计算机中的存储位置分布是杂乱的,但只要抓住了链表的头指针Head,实际上就抓住了表中所有结点。当Head=0时为空表,算法2.9 依次输出头指针为Head的线性表中各结点值,异常情况:,该算法涉及到的输入、输出数据:,空表时无输出,PROCEDURE PRTLL(V , Next , Head) j=Head While (j0) Do output V(j)j=Next(j) RETURN,P5556介绍了如何在C+语言中用动态分配内
33、存的方法实现链表,并用一段程序介绍在C+语言中如何创建链表,如何输出链表中各元素,自学,前面讨论的链表每个结点只有一个指针域,指向其后件地址,由该指针能方便找到其后件,但不能找到前件,这种链表称为线性单链表(单链表),在单链表中,只能顺指针向链尾方向扫描,当要寻找某个结点的前件时,只能从头指针开始重新寻找。为弥补单链表的不足,在应用中可设置两个指针域,一个指向前件,称为左指针;一个指向后件,称为右指针。这样的线性表称为双向链表,第i个结点:,逻辑状态图:,2、带链的栈,栈和队列是线性表,故栈和队列都可采用链式存储结构,Top,栈顶指针相当于链表头指针,0,在实际应用中,带栈的链可以用来收集计算
34、机存储空间中具有相同结构的空闲存储空间,这种带链的栈称为可利用栈。由于可利用栈链接了计算机存储空间中具有相同结构的空闲结点,因此,当计算机系统或用户程序需要存储结点时,可从中取出栈顶结点,当计算机系统或用户程序释放一个存储结点时,则将该结点放回到可利用栈的栈顶。,p,从可利用栈中取得一个结点p,p,将结点p送回可利用栈,用链式存储结构解决实际问题时,首先分配一定的存储空间形成可利用栈,再构造与可利用栈中结点具有相同结构的链表(可能有多个),这些链表中元素的插入结点取至可利用栈,删除的结点送回可利用栈。因此所有具有相同结构的链表可共用同一个可利用栈,算法2.10 从栈顶为Top的可利用栈取得一个
35、p,输入: 输出:,异常情况:,栈为空,获得结点失败,返回值P=,0 可利用栈无空间分配失败,0 可利用栈有空间分配成功,PROCEDURE new(p)p=TopIf p=0 Then ReturnTop=Next(Top)Return,算法2.11 将结点p送回栈顶为Top的可利用栈,输入: 输出:,异常情况:,无,PROCEDURE dispose(p)Next(p)=TopTop=pReturn,可利用栈是一个空表,是为其它链表服务的。以下算法是带链的栈的入栈与出栈运算,算法2.12 在栈顶为Top1的带链栈中插入一个元素x,输入: 输出:,异常情况:,可利用栈为空 分配新结点失败,p
36、,x,new(p) ; if p=0 then “无空间”,PROCEDURE PushLL( Top1 , x)new(p)If p=0 Then “无空间” ;Return V(p)=xNext(p)=Top1Top1=pReturn,算法2.13 在栈顶为Top1的带链栈中删除栈顶元素,p,输入: 输出:,异常情况:,栈空,不能删除,Top1=0,PROCEDURE POPLL( Top1 , y)If Top1=0 Then “栈空” ;Return y=V(Top1)p=Top1Top1=Next(Top1)dispose(p)Return,在C语言中用函数malloc()分配空间,
37、用free()释放空间 在C+语言中用new分配空间,用delete释放空间,3、带链的队列,排头指针(front)相当于链表头指针,尾指针(rear)指向链表最后一个元素,front,rear,队空(front=rear=0),改变头指针和尾指针的值,算法2.14 在带链队列中插入一个元素x,输入: 输出:,异常情况:,可利用栈为空,分配新结点失败,p,x,new(p) ; if p=0 then “无空间”,0,front=p rear=p,PROCEDURE ADDLL( rear , front , x)new(p)If p=0 Then “无空间” ;Return V(p)=xNex
38、t(p)=0If front0 Then Next(rear)=prear=pElserear=front=pReturn,算法2.15 在带链队列中删除一个元素,输入: 输出:,队中只有一个结点,删除该结点后,必须改变尾指针(rear)的值,front,p,异常情况:,队空,不能删除,front=0,rear=0,PROCEDURE DELLL( front , rear , y)If front=0 Then “队空” ;Return y=V(front)p=frontfront=Next(front)If front=0 Then rear=0dispose(p)Return,线性链表可
39、进行的基本运算即为线性表的基本运算,主要介绍前两种运算,在线性链表中,结点之间的关系是由指针的链接关系关系来表示,在对线性链表进行插入与删除时,只需改变指针即可,线性表插入、线性表删除、线性表查找、线性表排序、 线性表分解、线性表合并、线性表复制、线性表逆转,2.3.2 线性链表的基本运算,一、在线性链表中包含x元素的结点之前插入一个新元素b,p,b,1、为插入的新元素分配一个新结点p ,V(p)=b,2、在线性表中寻找包含元素x的前一个结点q,3、将结点p插入到结点q之后,b,p,单向链表,双向链表,单向链表 Next(p)=Next(q) Next(q)=p,双向链表 Llink(p)=q
40、 Rlink(p)=Rlink(q) Llink(Rlink(q)=p Rlink(q)=p,q,q,二、在线性链表中删除包含元素x的结点,p,1、在线性表中寻找包含元素x的前一个结点q,2、删除结点q的后一个结点,3、释放被删除的结点,p,单向链表,双向链表,单向链表 Next(q)=Next(Next(q),双向链表 Rlink(q)=Rlink(Rlink(q) Llink(Rlink(Rlink(q)=q,q,q,从上面分析可看出,线性表的插入与删除不涉及数据元素的移动,但也存在两个问题: 、插入时,从何处得到空闲的结点作为新元素结点;删除时,被删除结点应释放到何处才能被以后使用,即如
41、何管理空闲结点(用可利用栈)2、在非空链表中寻找包含指定元素的前一个结点,算法2.16 在头指针为Head的非空链表中寻找包含元素x的前一个结点q,输入: 输出:,2、x在表中第一个元素,异常情况:,1、空表,3、x不在表中,放入插入与删除 算法中考虑,q,PROCEDURE LookST( Head , x , q)q=HeadWhile ( Next(q) 0 ) and ( V(next(q) x ) Doq=Next(q)Return,如链表中未包含元素x,q指向,链表最后一个元素,即返回值 Next(q)=0 x不在链表中Next(q) 0 q为x前件地址,三、线性表的插入与删除算法
42、,算法2.1在头指针为Head的线性链表中包含元素x的结点前插入结点b,如链表中无元素x,则将b插入到链表的末尾。,、x在表中第一个元素,插在表头,异常情况:,、空表,插入结点为表中第一个结点,、x不在表中,插在表尾,输入: 输出:,Head=0,V(Head)=x,LookST(Head , x , q ) Next(q)=0,、无空间,不能插入,p,b,q,PROCEDURE InsLst( Head , x , b)new(p)If p=0 Then “无空间” ;Return V(p)=bIf Head=0 Then Head=p ; Next(p)=0 ; Return If V(H
43、ead)=x Then Next(p)=Head ; Head=p ; Return LookST( Head ,x,q )Next(p)=Next(q)Next(q)=pReturn,算法2.1在头指针为Head的线性链表中删除包含元素x的结点,、删除元素为表中第一个结点,异常情况:,、空表,不能删除,、x不在表中,不能删除,Head=0,V(Head)=x,LookST(Head , x , q ) Next(q)=0,PROCEDURE DelSt( Head , x )If Head=0 Then “空表” ; Return If V(Head)=x Then p=Next(Head)
44、 ; dispose(Head) ; Head=p ; Return LookST( Head ,x,q )If Next(q)=0 Then “无此结点” ; Return p=Next(q)Next(q)=Next(p)Dispose(p)Return,p,q,线性链表插入与删除示意图见书 P68 图2.26 P70图2.27,输入: 输出:,四、循环链表, 增加一个表头结点,数据域任意或根据需要设置,指针域指向线性链表的第一个结点,Head指向表头结点, 最后一个结点指针域不为空,而是指向表头结点,空循环链表,注意:, 循环链表可以从任何一个结点出发去访问其他结点, 循环链表和单链表判定
45、表的结束标志的方法不同:循环单链表的结束标志:Next(P)= Head单链表的结束标志: Next(P)= 0,循环链表的插入和删除算法和单链表类似。自学, 循环链表和单链表判定空表的方法不同:循环单链表为空表标志:Head = Next(Head)单链表为空表标志: Head = 0,1.顺序表占用的存储空间最少,而双链表占用的存储空间最多,2. 顺序表是一种随机存储结构,访问表中的某一个元素方便;单链表元素的访问则必须从头指针开始按顺序依次去寻找待访问的元素。,3. 一个顺序表一旦确定则其大小就不可以随意改变,因此操作中需要进行“判满”的工作,而链表的大小却可方便的改变,但链表占用的存储
46、空间较多。,4. 顺序表的操作主要消耗在元素的移动上,效率较低,单链表的操作消耗在指针的移动上,双链表的操作极为方便,但却是建立在存储空间的消耗上的。,总结:,五、线性表的应用 一元多项式相加,任何一个一元多项式Pn(x)都可按升幂表示为:Pn(x)=p0+p1x+p2x2+pixi+pnxn,可见Pn(x)由n+1个系数(p0,p1,pi,pn)唯一确定,可用一个线性表P来表示系数的集合,其中Pi(x)项的指数隐含在系数pi中。该线性表可表示为:P=(p0,p1,pi,pn)表长为n+1。,同理,再设一个一元多项式Qm(x),此多项式也可由一个线性表 Q=(q0,q1,qi,qm)(表长为m
47、+1)来表示。若要计算:Rn(x)=Pn(x)+Qm(x),这里不失一般性,假定mn。 Rn(x)也可用线性表R=(p0+q0,p1+q1,pm+qm,pm+1 ,, pn)来表示,显然可以对P、Q、R采用顺序结构存储,采用顺序表形式处理这种多项式的相加。,但是,若已知多项式为S(x)=1+3x10000+5x30000 ,此时再用将指数项隐含在系数中的方式,用系数顺序表来表示S(x),则其表长为30001,而表中只有3个非零元素,浪费了大量的存储空间。因此,一般情况下的一元n次多项式可写成:Pn(x)=P1xe1+P2xe2 + +Pixei+Pmxem ,其中Pi是指数为ei的非零系数项,
48、且满足0e1e2em,可用每个元素有两个数据项的线性表R=(P1 ,e1),(P2 ,e2),,(Pm ,em) )来表示。此线性表可用顺序和链式结构存储。,typedef struct poly int coef ;int exp ;elemtype ;,typedef struct polynty elemtype dataMax ;int num ;polynty ;,用顺序表的形式表示的一元多项式,仅用于只对多项式进行求值等不改变多项式系数和指数项(即不进行插入、删除等改变元素间的逻辑关系的操作)的运算。若要进行其它运算,则要采用链式存储结构。如:要实现一元多项式的加法运算,须涉及到插入、删除等改变元素逻辑关系的操作。,