第2章线性表2.ppt_第1页
第2章线性表2.ppt_第2页
第2章线性表2.ppt_第3页
第2章线性表2.ppt_第4页
第2章线性表2.ppt_第5页
已阅读5页,还剩46页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、,2.3 线性表的链式表示和实现: (链表linked list),用一组任意的存储单元(可以是无序的)存放线性表的数据元素,但也没有了顺序表随机存取的优点。 *无序-可零散地分布在内存中的任何位置上。 2.3.1 线性链表 链表中结点的逻辑次序和物理次序不一定相同。即:逻辑上相邻未必在物理上相邻。,为了表示数据元素之间的逻辑关系。除了存储数据本身之外,还需要存储一个指示其直接后继的信息(直接后继的存储位置),这两部分信息组成数据元素的存储映像,称为节点。 这两部分即为数据域和指针域。 结点之间的相对位置由链表中的指针域指示,指针域的值是该结点直接后继的地址。 存储数据元素本身信息的域称为数据

2、域。 指针域中存储的信息称为指针或链。,结点的组成:,数据域 指针域,数据域-表示数据元素自身值。 指针域(链域)-表示与其后继结点关系。 通过链域,可将n个结点按其逻辑顺序链接在一起(不论其物理次序如何)结成一个链表。,链表的组成:,头指针,31,上例表的逻辑状态:,zhao,qian,Sun,li,zhou,wu,zheng,wang ,head,用线性链表表示线性表时,节点中的指针表示数据元素之间的逻辑关系。或者说: 指针为数据元素之间的逻辑关系的映像,则逻辑上相邻的两个数据元素其存储的物理位置不要求紧邻,所以,这种存储结构为非顺序映像或链式映像。,线性单链表的存储结构 Typedef

3、struct lnode Elemtype data; Struct lnode *next; lnode,*linklist;,单链表:-每个结点只有一个链域。,开始结点-(无前趋)用头指针指向之。 最后一个结点(尾结点)-指针为空(无后继),用或null表示。 表中其它结点-由其前趋的指针域指向之。,a1,a2,an ,Head,假设P是指向线性表中第i个数据元素(节点ai)的指针,即 P-data=ai, 则p-next-data=ai+1 所以,在单链表中,要取得第i个数据元素,必须从头指针出发寻找。因此,单链表是非随机存取的存储结构。 有时,我们在单链表的第一个节点之前附设一个节点,

4、称为头节点。,*空表-头指针为空。其长度为0,a1,a2,an ,Head,单链表由头指针唯一确定,因此单链表可以用头指针的名字来命名。 例如:若头指针为head,则可把链表称为“表head”。,NULL,Head,Status getelem_ll(linklist L,int i,elemtype 算法的时间复杂度为 O(n),Getelem函数在单链表的实现:,指针p与指向的结点关系示意图:,data next,说明: p-指向链表中某一结点的指针(指针变量)。 *p-表示 由指针p所指向的结点。 (*p).data或p-data-表示由p所指向结点的数据域。 (*p).next或p-n

5、ext-表示由p所指向结点的指针域。,p,P-data,P-next,p=(node*)malloc(sizeof(node) =(linklist)malloc(sizeof(node) 对指针p赋值使其指向某一结点(按需生成一个node结点类型的新结点)。 其中: (node*)-进行类型转换。 sizeof(node)-求结点需用占用的字节数。 malloc(size)-在内存中分配size个连续可用字节的空间。 free(p)-系统回收p结点。(动态),结点的申请与释放:,结点插入的方法,a,b,a,b,x,s,p,插入前,插入后,p,1,2,结点插入的方法 如果插入位置合适 S-ne

6、xt=p-next; P-next=s;,结点删除的方法,p,删除前,删除后,p,b,c,a,b,c,a,结点删除的方法 如果删除位置正确 P-next=p-next- next 从中可以看出,在链表中元素插入或删除,只需修改指针而不需要移动元素。 先讲建线性表,B,A ,C,Head,S,建立单链表 头插法建表: 思想:从一个空表开始,重复读入数据,生成新结点,将读入数据存放在新结点的数据域中,然后将新结点插入到当前链表的表头上,直到读入结束标志为止。,D,B,A ,C,Head,S,头插法建表: 思想:从一个空表开始,重复读入数据,生成新结点,将读入数据存放在新结点的数据域中,然后将新结点

7、插入到当前链表的表头上,直到读入结束标志为止。,D,B,A ,C,Head,S,头插法建表: 思想:从一个空表开始,重复读入数据,生成新结点,将读入数据存放在新结点的数据域中,然后将新结点插入到当前链表的表头上,直到读入结束标志为止。,D,B,A ,C,Head,S,注:头插法生成的链表中结点的次序和输入的顺序相反。,头插法建表: 思想:从一个空表开始,重复读入数据,生成新结点,将读入数据存放在新结点的数据域中,然后将新结点插入到当前链表的表头上,直到读入结束标志为止。,D,void CREATELISTF() char x; /*逐个插入字符,以“x“为结束符,返回单链表头指针*/ node

8、 *head,*s; int n=0; /*n链表表长*/ head=NULL; /*链表开始为空*/ x=getchar(); /*读入第一个结点的值*/ while(x!=x) s=(node *)malloc(sizeof(node); /生成新结点*/ s-data=x;,s-next=head; head=s; n+; x=getchar(); /*CREATLISTF*/,头插法建表:,算法思想:将新结点插入到当前链表的表尾上,可增加一个尾指针r,使其始终指向链表的尾结点。,尾插建表法:,尾插建表可使生成的结点次序和输入的顺序相同,算法思想:将新结点插入到当前链表的表尾上,可增加一

9、个尾指针r,使其始终指向链表的尾结点。,A,C,B,尾插建表法:,head,r,S,r,D,尾插建表可使生成的结点次序和输入的顺序相同,void CREATLISTR() char x; /*逐个插入字符,以“x“为结束符*/ node *head,*s,*r; head=NULL; /*链表开始为空*/ r=NULL; /*尾指针初值为空*/ int n=0; x=getchar(); /*读入第一个结点的值*/ while(x!=x) /*“x”为输入结束符*/,s=(node *)malloc(sizeof(node); /生成新结点*/ s-data=x; if(head=NULL)

10、head=s; else r-next=s; r=s;n+; x=getchar(); If(r!=NULL) r-next=NULL; /*CREATLISTR*/, 尾插法建表:,尾插法建表分析:,上述尾插法建表由于没有生成(附加)头结点,因此开始结点和其它结点的插入处理并不一样。,尾插法建表的改进算法 思想: 设头结点,使第一个结点和其余结点的插入操作一致。,增加(表)头结点 头结点的数据域:可有可无 头结点的指针域:指向第一个结点的指针。,改进的尾插法建表算法,带头结点的单链表,空表,head,a1,an ,头结点,开始结点,非空表,无论链表是否为空,其头指针是指向头结点的非空指针,所

11、以表的第一个结点和其它结点的操作一致。,终端结点,void CREATLISTR1() /*带头结点的尾插法建立单链表,*/ char x; int n=0; node*head,*s,*r; head=(node*)malloc(sizeof(node); /*生成头结点*/ r=head; /*尾指针初值指向头结点*/ x=getchar(); while(x!=x) /*“x”为输入结束符*/,s=(node *)malloc(sizeof(node); /生成新结点*/ n+; s-data=x; r-next=s;/*新结点插入表尾*/ r=s;/*尾指针r指向新的表尾*/ x=ge

12、tchar();/*读下一结点*/ r-next=NULL; /*CREATLISTR1*/,改进的 尾插建表算法:,Status listinsert_l(LinkList /listinsert_L,在带头节点的单链表中第i个位置插入数据,Status listdelet_L(LinkList ,在带头节点的单链表中删除第i个位置的数据,插入和删除算法的时间复杂度: 按位置插入和删除一个,都需要先进行查找,所以时间复杂度为:O(n),按序号查找 设单链表的长度为n,要查找表中第i个结点,算法思想如下: 从头结点开始顺链扫描,用指针p指向当前扫描到的结点,用j作统计已扫描结点数的计数器,当p

13、扫描下一个结点时,j自动加1。 P的初值指向头结点,j的初值为0。 当j=i时,指针p所指的结点就是第i个结点。,查找运算,node *searchlist1(linklist L,int i) node *p; int j=0; p=L; while(p-next!=NULL ,合法位置为:1=i=n 带头结点,按值查找: 在链表中,查找是否有结点等于给定值key的结点,若有的话,则返回首次找到的值为key的结点的存储位置;否则返回null. 算法思想: 从开始结点出发,顺链逐个结点的值和给定值key作比较。,算法描述,Node *searchlist2(linklist L,datatyp

14、e x) /带头节点 node *p; int i=1; if(L=NULL) printf(tt链表下溢!n); return; if(L-next=NULL) printf(tt线性表为空!); return; p=L-next;,算法描述(续),while(p!=NULL ,设指针p指向单链表的某一结点,指针s指向要插入的、其值为x的新结点。 实现方法(两种): 已知节点后边插-将新结点*s插入结点*p之后。 已知节点前边插-将新结点*s插入结点*p之前。,插入运算,算法思想:取一新结点,将其数据域置为新结点,再修改有关结点的链域: 把原p结点的直接后继结点作为s结点的直接后继,s结点作

15、为p结点的直接后继。,X, 后插操作,S,P,INSERTAFTER(P,X) /*将值为X的新结点插入*P之后*/ node *p; datatype x; s=(node *)malloc(sizeof(node); /生成新结点*/ s-data=x; s-next=p-next; p-next=s;/*将*s插入*p之后*/ /*INSERTAFTER */,后插算法:,后插算法的时间复杂度: O(1),先找到p结点的前趋结点(单链表无前趋指针),然后修改其链域,使其指向待插入的s结点,而将s结点指向p结点。,X,前插操作:,S,q,p,INSERTBEFORE(p,x)/*在带头结点

16、的单链表head中,将值为X的新结点插入*P之前*/ node *p; datatype x; node *q; q=head; /*从头指针开始*/ if(q= =NULL) printf(“error!”); else s=(node*)malloc(sizeof(node); /*生成新结点*/ s-data=x; while(q-next!=p) q=q-next; /*找*p的前趋结点*/ s-next=p;q-next=s; /*将*s插入*p之 前,*q之后插*/ /*INSERTBEFORE */,前插算法:,前插算法的平均时间复杂度为:O(n),改进的前插入算法,算法思想:

17、后插算法为O(1),而前插算法为O(n),可在*p之后先插入新结点*s然后交换*s和*p的值。 算法描述:,插入前 p s 后插入 p s,A,X,A,X,交换调整 p s,x,A,INSERTBEFORE2(P,X) /*将值为X的新结点插入*P之后*/ node *p; datatype x,y; s=(node *)malloc(sizeof(node); /生成新结点*/ s-data=x; s-next=p-next; p-next=s;/*将*s插入*p之后*/ y=s-data; s-data=p-data; p-data=y; p=s; /*INSERTAFTER */,Void hb_l(linklist ,两个有序链表的合并,两个有序链表的合并 算法的时间复杂度: O(la.length+lb.length) 而空间复杂度为O(1),静态链表 : 用一维数组来描述链表。 这种存储结构仍需要预先分配一个较大的空间,只是在线性表的删除和插入时

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论