第二章 线性表091001.ppt
《第二章 线性表091001.ppt》由会员分享,可在线阅读,更多相关《第二章 线性表091001.ppt(92页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第二章线性表线性结构特点:在数据元素的非空有限集中存在唯一的一个被称作“第一个”的数据元素存在唯一的一个被称作“最后一个”的数据元素除第一个外,集合中的每个数据元素均只有一个前驱除最后一个外,集合中的每个数据元素均只有一个后继2.1 线性表的类型定义线性表的类型定义1、线性表、线性表线性表线性表(Linear List):由由n(n0)个数据元素个数据元素(结点结点)a1,a2,an组成的有限序列。组成的有限序列。其中:数据元素的个数其中:数据元素的个数n定义为表的定义为表的长度长度。当当n=0时称为时称为空表空表 常将非空的线性表常将非空的线性表(n0)记作:记作:(a1,a2,an)说明说
2、明:数据元素:数据元素ai(1i n)只是一个抽象的符号,只是一个抽象的符号,其具体含义在不同的情况下可以不同。其具体含义在不同的情况下可以不同。例例1、26个英文字母组成的字母表个英文字母组成的字母表 (A,B,C、Z)例3、学生健康情况登记表如下:姓名学号性别年龄健康情况王小林790631男18健康陈红790632女20一般刘建平790633男21健康张立立790634男17神经衰弱.例2、某校从1978年到1983年各种型号的计算机拥有量的变化情况:(6,17,28,50,92,188)例4、一副扑克的点数(2,3,4,J,Q,K,A)从以上例子可看出线性表线性表的逻辑特征逻辑特征是:在
3、非空的线性表,有且仅有一个开始结点在非空的线性表,有且仅有一个开始结点a1,它没有直接前趋,而仅有一个直接后继它没有直接前趋,而仅有一个直接后继a2;有且仅有一个终端结点有且仅有一个终端结点an,它没有直接后继,它没有直接后继,而仅有一个直接前趋而仅有一个直接前趋a n-1;其余的内部结点其余的内部结点ai(2 i n-1)都有且仅有一都有且仅有一个直接前趋个直接前趋a i-1和一个直接后继和一个直接后继a i+1。线性表是一种典型的线性结构线性表是一种典型的线性结构。2、抽象数据类型线性表线性表的定义ADT List 数据对象数据对象:Dai|aiElemSet,i=1,2,.,n,n0 数
4、据关系数据关系:R1|ai-1,aiD,i=2,.,n基本操作基本操作:InitList(&L)初始化初始化 操作结果:构造一个空的线性表L。DestroyList(&L)结构销毁结构销毁 初始条件:线性表L已存在。操作结果:销毁线性表L。引用型操作引用型操作 ListEmpty(L)初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则FALSE。ListLength(L)初始条件:线性表L已存在。操作结果:返回L中元素个数。GetElem(L,i,&e)初始条件:线性表L已存在,1iLengthList(L)操作结果:用e返回L中第i个元素的值。LocateElem(L,e,
5、compare()初始条件:线性表L已存在,compare()是元素判定函数。操作结果:返回L中第第1个个与e满足满足关系compare()的元素的位序。若这样的元素不存在,则返回值为0。PriorElem(L,cur_e,&pre_e)初始条件:线性表L已存在。操作结果:若cur_e是L的元素,但不是第一个,则用pre_e返回它的前驱,否则操作失败,pre_e无定义。NextElem(L,cur_e,&next_e)初始条件:线性表L已存在。操作结果:若cur_e是L的元素,但不是最后一个,则用next_e返回它的后继,否则操作失败,next_e无定义。ListTraverse(L,visi
6、t()初始条件:线性表L已存在。操作结果:依次依次对L的每个元素调用函数visit()。一旦visit()失败,则操作失败。加工型操作加工型操作 ClearList(&L)初始条件:线性表L已存在。操作结果:将L重置为空表。PutElem(L,i,&e)初始条件:线性表L已存在,1iLengthList(L)操作结果:L中第i个元素赋值同e的值。ListInsert(&L,i,e)初始条件:线性表L已存在,1iLengthList(L)+1操作结果:在L的第i个元素之前插入新的元素e,L的长度增1。ListDelete(&L,i,&e)初始条件:线性表L已存在且非空,1iLengthList(
7、L)操作结果:删除L的第i个元素,并用e返回其值,L的长度减1。ADTListvoid union(List&La,List Lb)La _ len=Listlength(La);Lb_len=Listlength(Lb);for(i=1;i=Lb _ len;i+)GetElem(Lb,i,e);if(!LocateElem(La,e,equal)ListInsert(La,+La _ len,e);例2-1利用两个线性表LA和LB分别表示两个集合A和B,现要求一个新的集合A=AB。3 3、算法讲解、算法讲解算法算法2.2例例2-2 已知线性表已知线性表LA和线性表和线性表LB中的数中的数据
8、元素按值非递减有序排列,现要求将据元素按值非递减有序排列,现要求将LA和和LB归并为一个新的线性表归并为一个新的线性表LC,且且LC中的元素仍按值非递减有序排列。中的元素仍按值非递减有序排列。此问题的算法如下:此问题的算法如下:void MergeList(List La,List Lb,List&Lc)InitList(Lc);i=j=1;k=0;La_len=ListLength(La);Lb _ len=ListLength(Lb);while(i=La_len)&(j=Lb_len)GetElem(La,i,ai);GetElem(Lb,j,bj);if(ai=bj)ListInser
9、t(Lc,+k,ai);+i;else ListInsert(Lc,+k,bj);+j;while(i=La _ len)GetElem(La,i+,ai);ListInsert(Lc,+k,ai);while(j=Lb _ len)GetElem(Lb,j+,bj);ListInsert(Lc,+k,bi);数据的运算是定义在逻辑结构上的,而运算的数据的运算是定义在逻辑结构上的,而运算的具体实现则是在存储结构上进行的。具体实现则是在存储结构上进行的。2.2 线性表的顺序表示和实现线性表的顺序表示和实现2.2.1顺序表把线性表的结点按逻辑顺序依次存放在一组地址连续的存储单元里。用这种方法存储的
10、线性表简称顺序表。假设线性表的每个元素需占用L个存储单元,并以所占的第一个单元的存储地址作为数据元素的存储位置。则线性表中第i+1个数据元素的存储位置LOC(ai+1)和第i个数据元素的存储位置LOC(ai)之间满足下列关系:LOC(ai+1)=LOC(ai)+L线性表的第i个数据元素ai的存储位置为:LOC(ai)=LOC(a1)+(i-1)*L图示a1a2aibb+L b+L*(I-1)12i内存元素序号 b+L*(n-1)备用空间an n返回typedef struct card int num;char name20;char author10;char publisher30;flo
11、at price;elemtype;#defineLIST_INIT_SIZE100/线性表初始空间,是单位空间的倍数#defineLISTINCREMENT10/分配空间增量typedefstructElemType*elem;/存储空间起始地址intlength;/当前长度intlistsize;/当前分配空间SqList;例如:SqListl,*pl;下面为用C语言描述的可动态分配的一维数组:2.2.2 顺序表上实现的基本操作顺序表上实现的基本操作 在顺序表存储结构中,很容易实现线性表的一在顺序表存储结构中,很容易实现线性表的一些操作,如线性表的构造、第些操作,如线性表的构造、第i个元素
12、的访问。个元素的访问。1.1.顺序表的初始化顺序表的初始化:顺序表的初始化即构造一个顺序表的初始化即构造一个空表空表。算法如下:。算法如下:Status InitList_Sq(SqList&L)L.elem=(ElemType*)malloc(sizeof(ElemType)*LIST_INIT_SIZE);if (!L.elem)exit(OVERFLOW);L.length=0;L.listsize=LIST_INIT_SIZE;returnOK;2、插入插入:线性表的插入运算是指在表的第i(1in+1)个位置上,插入一个新结点e,使长度为n的线性表(a1,ai-1,ai,an)变成长度
13、为n+1的线性表(a1,ai-1,e,ai,an)算法2.4图示StatusListInsert_sq(SqList&L,ElemTypee,inti)/在顺序线性表 L 的第i个元素之前插入新的元/素 e,i的合法值为1iL.length+1,若表/中容量不足,则按该顺序表的预定义增量扩容 if(iL.length+1)returnERROR;if(L.length=L.listsize)newbase=(ElemType*)(realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType);if(!newbase)exit(OVERFLO
14、W);L.elem=newbase;L.listsize+=LISTINCREMENT;q=&(L.elemi-1);for(p=&(L.elemL.length-1);p=q;-p)*(p+1)=*p;*q=e;+L.length;returnOK;内存a1a2aiai+1an01i-1数组下标n-1in12i元素序号i+1nn+1内存a1a2aiai+1an01i-1数组下标n-1in12i元素序号i+1nn+1an-1e返回现在分析算法的复杂度。这里的问题规模是表的长度,设它的值为n。该算法的时间主要花费在循环的结点后移语句上,该语句的执行次数(即移动结点的次数)是n-i+1。由此可看出
15、,所需移动结点的次数不仅依赖于表的长度,而且还与插入位置有关。当i=n时,由于循环变量的终值大于初值,结点后移语句将不进行;这是最好情况,其时间复杂度O(1);当i=1时,结点后移语句将循环执行n次,需移动表中所有结点,这是最坏情况,其时间复杂度为O(n)。算法时间复杂度T(n)设Pi是在第i个元素之前插入一个元素的概率,则在长度为n的线性表中插入一个元素时,所需移动的元素次数的平均次数为:也就是说,在顺序表上做插入运算,平均要移动表上一半结点。当表长n较大时,算法的效率相当低。虽然Eis(n)中n的的系数较小,但就数量级而言,它仍然是线性阶的。因此算法的平均时间复杂度为O(n)。3、删除删除
16、线性表的删除运算是指将表的第i(1in)结点删除,使长度为n的线性表:(a1,ai-1,ai,ai+1,an)变成长度为n-1的线性表(a1,ai-1,ai+1,an)内存a1a2aiai+1an01i-1V数组下标n-1in12i元素序号i+1nn+1内存a1a2ai+1V数组下标01i-1n-2in-112i元素序号i+1n-1nanai+2StatusListDelete(SqList&L,inti,ElemType&e)/在顺序线性表L中删除第 i 个元素,并用e/返回其值,i的合法值为 1iL.length。If(iL.length)returnERROR;p=&(L.elemi-1
17、);e=*p;q=L.elem+L.length-1;for(+p;p=q;+p)*(p-1)=*p;-L.length;returnOK;分析:该算法的时间分析与插入算法相似,结点的移动次数也是由表长n和位置i决定。若i=n,则由于循环变量的初值大于终值,前移语句将不执行,无需移动结点;若i=1,则前移语句将循环执行n-1次,需移动表中除开始结点外的所有结点。这两种情况下算法的时间复杂度分别为O(1)和O(n)。删除算法的平均性能分析与插入算法相似。在长度为n的线性表中删除一个结点,令Ede(n)表示所需移动结点的平均次数,删除表中第i个结点的移动次数为n-i,故式中,Qi表示删除表中第i个
18、结点的概率。在等概率的假设下,p1=p2=p3=pn=1/n由此可得:即在顺序表上做删除运算,平均要移动表中约一半的结点,平均时间复杂度也是O(n)。结论1:在顺序表中插入或删除一个元素时,平均移动表的一半元素,当n很大时,效率很低 4.4.按值查找按值查找 线性表中的按值查找是指在线性表中查找与给定值e相等的数据元素。在顺序表中完成该运算最简单的方法是:从第一个元素 a1 起依次和e比较,直到找到一个与e相等的数据元素,则返回它在顺序表中的存储下标或序号(二者差一);或者查遍整个表都没有找到与 e 相等的元素,返回-1或0。intLocate_Sq(SqListL,ElemTypee)i=0
19、;/此题与书不同p=L.elem;2.2.3 顺序表应用举例顺序表应用举例while(i=L.length)return-1;elsereturni;/*返回的是存储位置*/算法2.6 例例 1有顺序表A和B,其元素均按从小到大的升序排列,编写一个算法将它们合并成一个顺序表C,要求C的元素也是从小到大的升序排列。算法思路:依次扫描通过A和B的元素,比较当前的元素的值,将较小值的元素赋给C,如此直到一个线性表扫描完毕,然后将未完的那个顺序表中余下部分赋给C即可。C的容量要能够容纳A、B两个线性表相加的长度。voidMergeList_Sq(SqListLa,SqListLb,SqList&Lc)
20、pa=La.elem;pb=Lb.elem;Lc.listsize=Lc.length=La.length+Lb.length;pc=Lc.elem=(ElemType*)malloc(Lc.listsize*sizeof(ElemType);if(!Lc.elem)exit(OVERFLOW);pa_last=La.elem+La.length-1;pb_last=Lb.elem+Lb.length-1;while(pa=pa_last&pb=pb_last)if(*pa=*pb)*pc+=*pa+;else*pc+=*pb+;while(pa=pa_last)*pc+=*pa+;while
21、(pbdata表示p指向结点的数据域(*p).nextp-next表示p指向结点的指针域 说明:通常将标识链表的头指针说明为头指针说明为LinkListLinkList类型类型的变量,如:LinkListLinkList head head;当head有定义时,NULL,则表示一个空表;第一个结点的地址,即链表的头指针;将指向某结点的指针变量说明为指针变量说明为LNodeLNode *类型类型,如:LNodeLNode *p *p;例如:p=malloc(sizeof(LNode);free(p);引用方法引用方法 练习:指针赋值的操作练习:指针赋值的操作指针指向结点指针指向结点 p=qq p
22、指针指向后继指针指向后继 p=q-next指针移动指针移动 p=p-nextqppppq链指针改接链指针改接 p-next=q链指针改接后继链指针改接后继 p-next=q-nextpq练习:指针赋值的操作练习:指针赋值的操作ZHAOQIANSUNLIZHOUWUZHENGWANGH 例例 线性表线性表 (ZHAO,QIAN,SUN,LI,ZHOU,WU,ZHENG,WANG)43131NULL3771952数据域指针域LIQIANSUNWANGWUZHAOZHENGZHOU存储地址1713192531374331H头指针110130135160头指针head165170200205hat20
23、0.cat135eat170.matNullbat130fat110jat205lat160165例1、已知线形表的链式表示如下:求该线形表 线性表:(bat,cat,eat,fat,hat,jat,lat,mat)bat cat eat mat head 二、基本算法二、基本算法1 1、建立单链表、建立单链表动态地建立单链表的常用方法有如下两种:动态地建立单链表的常用方法有如下两种:1)1)头插法建表头插法建表 该方法从一个空表开始,重复读入数据,生成新结点,该方法从一个空表开始,重复读入数据,生成新结点,将读入数据存放到新结点的数据域中,然后将新结点插入将读入数据存放到新结点的数据域中,然
24、后将新结点插入到当前链表的表头上,直到读入结束标志为止。到当前链表的表头上,直到读入结束标志为止。StatusStatusCreateList(LinkListLinkList&L&L)/表长不定L=NULL;/先建立一个空的单链表先建立一个空的单链表 scanf(x);while(x!=FLAG)p=(LNode*)malloc(sizeof(LNode);/省略不成功时的语句pdata=x;pnext=L;L=p;scanf(x);returnOK;/CreateList 254218762976182542182542254225在头部插入建立单链表在头部插入建立单链表2、尾插法建表尾插
25、法建表 头插法建立链表虽然算法简单,但头插法建立链表虽然算法简单,但生成的链表中结点的次序和输入的顺序生成的链表中结点的次序和输入的顺序相反。若希望二者次序一致,可采用尾相反。若希望二者次序一致,可采用尾插法建表。该方法是将新结点插入到当插法建表。该方法是将新结点插入到当前链表的表尾上,为此必须增加一个尾前链表的表尾上,为此必须增加一个尾指针指针r r,使其始终指向当前链表的尾结使其始终指向当前链表的尾结点。点。例:初始状态:头指针初始状态:头指针H=NULL,尾指针尾指针 r=NULL;按线性按线性表中元素的顺序依次读入数据元素,不是结束标志时,表中元素的顺序依次读入数据元素,不是结束标志时
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第二章 线性表091001 第二 线性 091001
限制150内