收藏 分享(赏)

【零基础学数据结构】第3章 线性表---机械工业,陈锐 著,月畅销第11,周畅销第2.ppt

上传人:gnk289057 文档编号:6418349 上传时间:2019-04-12 格式:PPT 页数:69 大小:1.38MB
下载 相关 举报
【零基础学数据结构】第3章  线性表---机械工业,陈锐 著,月畅销第11,周畅销第2.ppt_第1页
第1页 / 共69页
【零基础学数据结构】第3章  线性表---机械工业,陈锐 著,月畅销第11,周畅销第2.ppt_第2页
第2页 / 共69页
【零基础学数据结构】第3章  线性表---机械工业,陈锐 著,月畅销第11,周畅销第2.ppt_第3页
第3页 / 共69页
【零基础学数据结构】第3章  线性表---机械工业,陈锐 著,月畅销第11,周畅销第2.ppt_第4页
第4页 / 共69页
【零基础学数据结构】第3章  线性表---机械工业,陈锐 著,月畅销第11,周畅销第2.ppt_第5页
第5页 / 共69页
点击查看更多>>
资源描述

1、第3章 线性表,线性表是一种最简单的线性结构。线性结构的特点是:在非空的有限集合,只有唯一的第一个元素和唯一的最后一个元素。第一个元素没有直接前驱元素,最后一个元素没有直接后继元素。其它元素都有唯一的前驱元素和唯一的后继元素。线性表可以用顺序存储结构和链式存储结构存储,可以在线性表的任意位置进行插入和删除操作 .,3.1 线性表的概念及运算,线性表是一种最简单且最常用的一种线性结构。本节主要介绍线性表的逻辑结构及在线性表上的运算。,3.1.1 线性表的逻辑结构,一个线性表由有限个类型相同的数据元素组成。在这有限个数据元素中,数据元素构成一个有序的序列,除了第一个元素和最后一个元素外,其它元素有

2、唯一的前驱元素和唯一的后继元素。在简单的线性表中,可以把每一英文单词看成是一个线性表。表中的每一英文字母就是一个数据元素,每个数据元素之间存在着唯一的顺序关系。,3.1.1 线性表的逻辑结构,在较复杂的线性表中,一个数据元素可以由若干个数据项组成,如图3.2所示的一个学校的教职工情况表中,一个数据元素由姓名、性别、出生年月、籍贯、学历、职称及任职时间七个数据项组成。这时,数据元素也称为记录。,3.1.2 线性表的抽象数据类型,1数据对象集合 2基本操作集合,3.2 线性表的顺序表示与实现,要在计算机上实现线性表的操作,必须将其逻辑结构转化为计算机可以识别的存储结构形式。线性表的存储结构主要有两

3、种:顺序存储结构和链式存储结构。本节的主要学习内容包括线性表的顺序存储结构及顺序存储结构下的操作实现。,3.2.1 线性表的顺序存储结构,线性表的顺序存储指的是将线性表中的元素存放在一组连续的存储单元中。这样的存储方式使得线性表逻辑上相邻的元素,其在物理存储单元也是相邻的。采用顺序存储结构的线性表称为顺序表。 假设线性表有n个元素,每个元素占用m个存储单元,如果第一个元素的存储位置记为LOC(a1),第i个元素的存储位置记为LOC(ai),第i+1个元素的存储位置记为LOC(ai+1)。,3.2.1 线性表的顺序存储结构,线性表的顺序存储结构描述如下。 #define ListSize 100

4、 typedef struct DataType listListSize;int length; SeqList;,3.2.2 顺序表的基本运算,在顺序存储结构中,线性表的基本运算如下。以下算法的实现保存在文件“SeqList.h”中。,3.2.2 顺序表的基本运算,(1)线性表的初始化操作。线性表的初始化就是将线性表初始化为空表,只需要将线性表的长度置为0即可。线性表的初始化实现代码如下。 void InitList(SeqList *L) L-length=0; /*把线性表的长度置为0*/ ,3.2.2 顺序表的基本运算,(2)判断线性表是否为空。线性表为空的标志就是线性表的长度len

5、gth为0。判断线性表是否为空的实现代码如下。 int ListEmpty(SeqList L) if(L.length=0) /*判断线性表的长度是否为0*/return 1;/*当线性表为空时,返回1;否则返回0*/elsereturn 0; ,3.2.2 顺序表的基本运算,(3)按序号查找操作。 int GetElem(SeqList L,int i,DataType *e) /*在查找第i个元素之前,判断该序号是否合法*/if(iL.length) return -1;*e=L.listi-1; /*将第i个元素的值赋值给e*/return 1; ,3.2.2 顺序表的基本运算,(4)

6、按内容查找操作。 int LocateElem(SeqList L,DataType e) int i;for(i=0;iL.length;i+) /*从第一个元素开始比较*/if(L.listi=e)return i+1;return 0; ,3.2.2 顺序表的基本运算,(5)插入操作。,3.2.2 顺序表的基本运算,(6)删除操作。,3.2.2 顺序表的基本运算,(7)返回线性表的长度操作。 int ListLength(SeqList L) return L.length; ,3.2.2 顺序表的基本运算,(8)清空操作。 void ClearList(SeqList *L) L-le

7、ngth=0; ,3.2.3 顺序表的实现算法分析,在以上顺序表的实现算法中,除了按内容查找运算、插入和删除操作外,其它算法的时间复杂度都为O(1)。 在按内容查找算法中,如果要查找的元素在第一个位置,则需要比较一次;如果要查找的元素在最后一个位置,则需要比较n次,n为线性表的长度。,3.2.3 顺序表的实现算法分析,在顺序表的插入算法中,时间的耗费主要集中在移动元素上。如果要插入的元素在第一个位置,则需要移动元素的次数为n次;如果要插入的元素在最后一个位置,则需要移动元素次数为1次;如果插入位置在最后一个元素之后,即第n+1个位置,则需要移动次数为0次。,3.3 顺序表的应用举例,本节通过几

8、个实例来说明顺序表基本运算的应用。 例3_1 利用线性表的基本运算,实现如果在线性表A中出现的元素,在线性表B中也出现,则将A中该元素删除。,for(i=0;i0)DeleteList(A,pos,/*如果找到该元素,将其从A中删除*/,3.3 顺序表的应用举例,例3_2 顺序表A和顺序表B的元素都是非递减排列,利用线性表的基本运算,将它们合并成一个顺序表C,要求C也是非递减排列。例如,A=(6,11,11,23),B=(2,10,12,12,21),则C=(2,6,10,11,11,12,12,21,23)。,3.4 线性表的链式表示与实现,在顺序表中,由于逻辑上相邻的元素其物理位置也相邻,

9、因此可以随机存取顺序表中的任何一个元素。但同时顺序表也存在着以下缺点:插入和删除运算需要移动大量的元素,存储空间必须事先进行分配,事先分配的存储单元大小可能不适合问题的需要。链式存储的线性表可以克服顺序表的以上缺点,本节的主要学习内容包括单链表的存储结构及单链表的运算。,3.4.1 单链表的存储结构,线性表的链式存储是采用一组任意的存储单元存放线性表的元素。这组存储单元可以是连续的,也可以是不连续的。为了表示每个元素与其直接后继的逻辑关系,除了需要存储元素本身的信息外,还需要存储指示其后继元素的地址信息。这两部分组成的存储结构,称为结点。结点包括两个域:数据域和指针域。,3.4.1 单链表的存

10、储结构,3.4.2 单链表上的基本运算,单链表的存储结构用C语言描述如下: typedef struct Node DataType data;struct Node *next; ListNode,*LinkList;,3.4.2 单链表上的基本运算,单链表上的基本运算包括单链表的建立、单链表的插入、单链表的删除、求单链表的长度等。带头结点的单链表的运算具体实现如下。以下算法的实现保存在文件“LinkList.h”中。,3.4.2 单链表上的基本运算,(1)单链表的初始化操作。 void InitList(LinkList *head) if(*head=(LinkList)malloc(s

11、izeof(ListNode)=NULL) /*为头结点分配一个存储空间*/exit(-1);(*head)-next=NULL; /*将单链表的头结点指针域置为空*/ ,3.4.2 单链表上的基本运算,(2)判断单链表是否为空。 int ListEmpty(LinkList head) if(head-next=NULL) /*判断单链表头结点的指针域是否为空*/return 1;/*当单链表为空时,返回1;否则返回0*/elsereturn 0; ,3.4.2 单链表上的基本运算,(3)按序号查找操作。按序号查找就是查找单链表中的第i个结点,如果找到返回该结点的指针。否则,返回NULL表示

12、失败。,3.4.2 单链表上的基本运算,(4)按内容查找操作。 ListNode *LocateElem(LinkList head,DataType e) ListNode *p;p=head-next; /*指针p指向第一个结点*/while(p)if(p-data!=e) /*找到与e相等的元素,返回该序号*/p=p-next;elsebreak;return p; ,3.4.2 单链表上的基本运算,(5)定位操作。有时,为了删除第i个结点,需要根据内容查找到该结点,返回该结点的序号。按内容查找并返回结点的序号的函数也称为定位函数。定位函数也是通过从单链表的头指针出发,依次访问每个结点,

13、并将结点的值与e比较,如果相等,返回该序号表示成功;如果没有与e值相等的元素,返回0表示失败。,3.4.2 单链表上的基本运算,(6)插入操作。,3.4.2 单链表上的基本运算,(7)删除操作。,3.4.2 单链表上的基本运算,(8)求表长操作。 int ListLength(LinkList head) ListNode *p;int count=0;p=head;while(p-next!=NULL)p=p-next;count+;return count; ,3.4.2 单链表上的基本运算,(9)销毁链表操作。 void DestroyList(LinkList head) ListNo

14、de *p,*q;p=head;while(p!=NULL)q=p;p=p-next;free(q); ,3.5 单链表应用举例,例3_3 利用单链表的基本运算,实现如果在单链表A中出现的元素,在单链表B中也出现,则将A中该元素删除。,3.5 单链表应用举例,3.5 单链表应用举例,例3_4 存在两个单链表A和B,其中的元素都是非递减排列,编写算法归并单链表A和B得到单链表C,C的元素的值按照非递减排列。要求表C利用原来表A和B的结点空间,不申请额外空间。,3.6 循环单链表,循环单链表是另一种形式的单链表。本节的主要学习内容包括循环单链表的链式存储结构及循环单链表的应用。,3.6.1 循环链

15、表的链式存储,循环单链表是一种首尾相连的单链表。它是在单链表的基础上,将单链表的最后一个结点的指针域由NULL变成指向单链表的头结点或第一个结点,这样的单链表称为循环单链表。与单链表类似,循环单链表也有带头结点结构和不带头结点结构两种。,3.6.1 循环链表的链式存储,3.6.1 循环链表的链式存储,3.6.2 循环单链表的应用,例3_5 有两个循环单链表,头指针分别是head1和head2,实现算法将链表head2连接在head1之后,连接后的链表仍然是循环链表的形式。,3.6.2 循环单链表的应用,例3_6 约瑟夫问题。有n个人,编号为1,2,n,围成一个圆圈,按照顺时针方向从编号为k的人

16、从1开始报数,报数为m的人出列,他的下一个人重新开始从1报数,数到m的人出列,照这样重复下去,直到所有的人都出列。编写一个算法,要求输入n、k和m,按照出列的顺序输出编号。,3.7 双向链表,单链表和循环单链表的每一个结点的指针域只有一个,要查找指针p指向结点的直接前驱结点,必须从p指针出发,顺着指针域把整个链表访问一遍,找到该结点,其时间复杂度是O(n)。为了克服单链表的这种缺点,可以利用双向链表解决。本节的主要学习内容包括双向链表的存储结构及双向链表存储结构下的操作实现。,3.7.1 双向链表的存储结构,双向链表是指链表中的每个结点有两个指针域:一个指向直接前驱结点,另一个指向直接后继结点

17、。 在双向循环链表中,每个结点包括三个域:data域、prior域和next域。其中,data域为数据域,存放数据元素;prior域为前驱结点指针域,指向直接前驱结点;next域为后继结点域,指向直接后继结点。,3.7.1 双向链表的存储结构,双向链表也分为带头结点和不带头结点两种,带头结点使某些操作更加方便。另外,双向链表也有循环结构,称为双向循环链表。带头结点的双向循环链表如图3.31所示。双向循环链表为空的情况如图3.32所示,判断带头结点的双循环链表为空的条件是head-prior=head或head-next=head。,3.7.2 双向链表的插入操作和删除操作,双向链表的有些操作,

18、如求链表的长度、查找链表的第i个结点等,与单链表中的算法实现基本没什么差异。但是对于双向循环链表的插入和删除操作,因为涉及到的是前驱结点指针和后继结点指针,所以需要修改两个方向的指针。 1插入操作 2删除操作,3.7.2 双向链表的插入操作和删除操作,1插入操作,3.7.2 双向链表的插入操作和删除操作,2删除操作,3.8 双向链表的应用,例3.7 编写算法实现建立一个带头结点的含n个元素的双向循环链表H,并在链表H中第i个位置插入一个元素e。例如,建立一个双向循环链表(A,B,C,D,E,F),元素为字符型数据,在链表中第3个位置插入元素X,则链表变为(A,B, X,C,D,E,F)。,3.

19、8 双向链表的应用,3.9 静态链表,前面介绍的各种链表如单链表、循环链表等结点之间的关系都是由指针实现的,结点的分配与释放都是由函数malloc和free动态实现,因此称为动态链表。但是有的高级程序设计语言没有指针类型,如Basic、Fortran等,本节利用静态链表实现动态链表的功能。,3.9.1 静态链表的存储结构,静态链表可通过一维数组来描述,用游标模拟指针。游标的作用就是指示元素的直接后继。这里的游标的数据类型不再是动态链表的指针类型,而是一个整型。 要实现静态链表,通过定义一个结构体数组作为结点空间,结点包括两个域:数据域和指针域。数据域用于存放结点的数据信息,指针域指向直接后继元

20、素。,3.9.2 静态链表的实现,(1)静态链表的初始化操作。 void InitSList(SLinkList *L) /*静态链表初始化。*/ int i;for(i=0;iListSize;i+)(*L).listi.cur=i+1;(*L).listListSize-1.cur=0;(*L).av=1; ,3.9.2 静态链表的实现,(2)分配结点。 int AssignNode(SLinkList L) /*从备用链表中取下一个结点空间,分配给要插入链表中的元素*/ int i;i=L.av;L.av=L.listi.cur;return i; ,3.9.2 静态链表的实现,(3)回

21、收结点。 void FreeNode(SLinkList L,int pos) /*使空闲结点成为备用链表中的结点*/ L.listpos.cur=L.av;L.av=pos; ,3.9.2 静态链表的实现,(4)插入操作。 void InsertSList(SLinkList *L,int i,DataType e) int j,k,x;k=(*L).av;(*L).av=(*L).listk.cur;(*L).listk.data=e;j=(*L).list0.cur;for(x=1;xi-1;x+)j=(*L).listj.cur;(*L).listk.cur=(*L).listj.cu

22、r;(*L).listj.cur=k; ,3.9.2 静态链表的实现,(5)删除操作。 void DeleteSList(SLinkList *L,int i,DataType*e) int j,k,x;j=(*L).list0.cur;for(x=1;xi-1;x+)j=(*L).listj.cur;k=(*L).listj.cur;(*L).listj.cur=(*L).listk.cur;(*L).listk.cur=(*L).av;*e=(*L).listk.data;(*L).av=k; ,3.9.3 静态链表的应用,例3.8 创建一个静态链表,通过输入元素及位置插入一个元素,然后通

23、过输入删除元素的位置删除元素。例如,创建一个静态链表A,B,C,D,E,F,H,在表的第3个位置插入元素x,然后将表的第6个元素删除。,3.10 各种线性表的操作,例3.9 编写一个算法,将一个顺序表A分拆成两个部分,使A中大于等于0的元素放在左边,小于0的元素放在右边。要求不占用额外的存储空间,即空间复杂度为O(1)。例如,顺序表(-7,0,5,-8,9,-4,3,-2)经过分拆调整后变为(3,0,5,9,-8,-4,-7,-2)。,3.10 各种线性表的操作,例3.10 如果线性表分别采用顺序存储结构和链式(带头结点)存储结构,请写出它们的就地逆置算法。,3.10 各种线性表的操作,例3_

24、11 已知有两个带头结点的双向循环链表A和B,它们的元素均是按照递增排列,编写算法,将A和B合并成一个双向循环链表,并使合并后链表中的元素也按照递增排列。,3.10 各种线性表的操作,3.11 一元多项式的表示与相乘,本节通过分析一元多项式的表示与相乘的链式实现作为本章的结束。一元多项式的相乘是线性表在生活中一个实际应用,它的各种操作集中了本节所学的知识,通过一元多项式的乘法链式实现,培养算法设计思想的具体应用。本节的主要内容包括一元多项式的表示和一元多项式的乘法实现。,3.11.1 一元多项式的表示,在数学中,一个一元多项式An(x)可以写成降幂的形式: An(x)=anxn+an-1xn-

25、1+a1x+a0 如果an0,则An(x)被称为n阶多项式。一个n阶多项式由n+1个系数构成。一个n阶多项式的系数可以用线性表(an,an-1,a1,a0)表示。 一元多项式An(x)=anxn+an-1xn-1+a1x+a0的系数和指数同时存放,可以表示成一个线性表,线性表的每一个数据元素由一个二元组构成。因此,多项式An(x)可以表示成线性表 (an,n),(an-1,n-1),(a1,1),(a0,0) 多项式P(x)可以表示成(10,2001),(1,1),(1,0)的形式。,3.11.1 一元多项式的表示,typedef struct polyn float coef;int exp

26、n;struct polyn *next; PloyNode,*PLinkList;S(x)=7 x6+3 x4-3 x2+6,3.11.2 一元多项式相乘,两个一元多项式的相乘运算,需要将一个多项式的每一项的指数与另一个多项式的每一项的指数相加,并将其系数相乘。假设两个多项式An(x)=anxn+an-1xn-1+a1x+a0和Bm(x)=bmxm+bm-1xm-1+b1x+b0,要将这两个多项式相乘,就是将多项式An(x)中的每一项与Bm(x)相乘,相乘的结果用线性表表示为(an*bm,n+m),(an-1*bm,n+m-1),(a1,1),(a0,0)。 1一元多项式的创建 2两个一元多项式的相乘 3测试代码,3.12 小结,本章主要介绍了一种最简单也是最常用的数据结构线性表。 线性表是一种可以在任意位置进行插入和删除操作,由n个同类型的数据元素组成的一种线性数据结构。线性表中的每个数据元素只有一个前驱元素和只有一个后继元素。其中,第一个数据元素没有前驱元素,最后一个数据元素没有后继元素。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 实用文档 > 统计图表

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报