




免费预览已结束,剩余86页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1,第十一章链表,2,例:跳马。依下图将每一步跳马之后的位置(x,y)放到一个“结点”里,再用“链子穿起来”,形成一条链,相邻两结点间用一个指针将两者连到一起。,结构的概念与应用,3,依上图有7个结点,为了表示这种既有数据又有指针的情况,引入结构这种数据类型。,4,11.7用指针处理链表,链表是程序设计中一种重要的动态数据结构,它是动态地进行存储分配的一种结构。,动态性体现为:链表中的元素个数可以根据需要增加和减少,不像数组,在声明之后就固定不变;元素的位置可以变化,即可以从某个位置删除,然后再插入到一个新的地方;,5,1、链表中的元素称为“结点”,每个结点包括两个域:数据域和指针域;2、单向链表通常由一个头指针(head),用于指向链表头;3、单向链表有一个尾结点,该结点的指针部分指向一个空结点(NULL)。,Head1249135614751021,结点里的指针是存放下一个结点的地址,6,链表中结点的定义,链表是由结点构成的,关键是定义结点;链表的结点定义打破了先定义再使用的限制,即可以用自己定义自己;递归函数的定义也违反了先定义再使用;这是C语言程序设计上的两大特例,7,链表的基本操作,对链表的基本操作有:(1)创建链表是指,从无到有地建立起一个链表,即往空链表中依次插入若干结点,并保持结点之间的前驱和后继关系。(2)检索操作是指,按给定的结点索引号或检索条件,查找某个结点。如果找到指定的结点,则称为检索成功;否则,称为检索失败。(3)插入操作是指,在结点ki-1与ki之间插入一个新的结点k,使线性表的长度增1,且ki-1与ki的逻辑关系发生如下变化:插入前,ki-1是ki的前驱,ki是ki-1的后继;插入后,新插入的结点k成为ki-1的后继、ki的前驱.,8,(4)删除操作是指,删除结点ki,使线性表的长度减1,且ki-1、ki和ki+1之间的逻辑关系发生如下变化:删除前,ki是ki+1的前驱、ki-1的后继;删除后,ki-1成为ki+1的前驱,ki+1成为ki-1的后继.(5)打印输出,9,一个指针类型的成员既可指向其它类型的结构体数据,也可以指向自己所在的结构体类型的数据,numScorenext,next是structstudent类型中的一个成员,它又指向structstudent类型的数据。换名话说:next存放下一个结点的地址,10,11.7.2简单链表,#defineNULL0structstudentlongnum;floatscore;structstudent*next;main()structstudenta,b,c,*head,*p;a.num=99101;a.score=89.5;b.num=99103;b.score=90;c.num=99107;c.score=85;head=,例11.7,建立和输出一个简单链表,各结点在程序中定义,不是临时开辟的,始终占有内容不放,这种链表称为“静态链表”,11,11.7.3处理动态链表所需的函数,C语言使用系统函数动态开辟和释放存储单元,1.malloc函数,函数原形:void*malloc(unsignedintsize);作用:在内存的动态存储区中分配一个长度为size的连续空间。返回值:是一个指向分配域起始地址的指针(基本类型void)。执行失败:返回NULL,12,函数原形:void*calloc(unsignedn,unsignedsize);作用:在内存动态区中分配n个长度为size的连续空间。函数返回值:指向分配域起始地址的指针执行失败:返回null主要用途:为一维数组开辟动态存储空间。n为数组元素个数,每个元素长度为size,2.calloc函数,13,3.free函数,函数原形:voidfree(void*p);作用:释放由p指向的内存区。P:是最近一次调用calloc或malloc函数时返回的值。free函数无返回值动态分配的存储单元在用完后一定要释放,否则内存会因申请空间过多引起资源不足而出现故障。,14,结点的动态分配,ANSIC的三个函数(头文件malloc.h)void*malloc(unsignedintsize)void*calloc(unsignedn,unsignedsize)voidfree(void*p)C+的两个函数new类型(初值)delete指针变量/*表示释放数组,可有可无)*/使用new的优点:可以通过对象的大小直接分配,而不管对象的具体长度是多少(p340例14.10),15,11.7.4建立动态链表,基本方法:三个结点(头结点head、尾结点NULL和待插入结点P)第一步:定义头结点head、尾结点p2和待插入结点p1,待插入的结点数据部分初始化;第二步:该结点被头结点、尾结点同时指向。P1=p2=(structstudent*)malloc(LEN);头指针部分为空,head=NULL;第三步:重复申请待插入结点空间,对该结点的数据部分赋值(或输入值),将该结点插入在最前面,或者最后面(书上在尾部插入).P2-next=P1;P2=P1;最后:P2-next=NULL;,*head,*p1,*p2,使用malloc(LEN),P2-next=NULL;,16,11.7.4建立动态链表,head,P1p2,1.任务是开辟结点和输入数据2.并建立前后相链的关系,待插入的结点p1数据部分初始化,该结点被头结点head、尾结点p2同时指向.,17,图11.14,head,p2,p1,head,p2,p1,(a),(b),p1重复申请待插入结点空间,对该结点的数据部分赋值(或输入值),P2-next指向p1新开辟的结点。,18,图11.14,head,p1,p2,(c),P2指向新结点p2=p1,19,图11.15,p2,p1,head,p2,p1,head,(a),(b),20,图11.16,p2,p1,head,p2,p1,head,21,例11.8建立一个有3名学生数据的单向动态链表,#defineNULL0#defineLENsizeof(structstudent)structstudentlongnum;floatscore;structstudent*next;intn;structstudent*creat(void)structstudent*head;structstudent*p1,*p2;n=0;p1=p2=(structstudent*)malloc(LEN);scanf(%1d,%f,结构体类型数据的长度,sizeof是“字节数运算符”,定义指针类型的函数。带回链表的起始地址,开辟长度为LEN的内存区,P1,p2是指向结构体类型数据的指针变量,强行转换成结构体类型,假设头指向空结点,22,续,while(p1-num!=0)n=n+1;/*n是结点的个数*/if(n=1)head=p1;elsep2-next=p1;p2=p1;p1=(structstudent*)malloc(LEN);scanf(%1d,%f,/返回链表的头指针,算法:p1指向新开的结点:p1=(stuctstudent*)malloc(LEN);p1的所指向的结点连接在p2所指向结点后面,用p2-next=p1来实现。p2指向链表中最后建立的结点,:p2=p1;,头指针指向p1结点,P1开辟的新结点链到了p2的后面,P1继续开辟新结点,给新结点赋值此,23,11.7.5输出链表,链表遍历1.单向链表总是从头结点开始的;2.每访问一个结点,就将当前指针向该结点的下一个结点移动:p=p-next;3.直至下一结点为空P=NULL,24,图11.18,head,p,P,P,25,例题9,voidprint(structstudent*head)structstudent*p;printf(nNow,These%drecordsare:n,n);p=head;if(head!=NULL)doprintf(%ld%5.lfn,p-num,p-score);p=p-next;while(p!=NULL);,26,11.7.6对链表的删除操作,删除结点原则:不改变原来的排列顺序,只是从链表中分离开来,撤消原来的链接关系。两种情况:1、要删的结点是头指针所指的结点则直接操作;2、不是头结点,要依次往下找。另外要考虑:空表和找不到要删除的结点,27,链表中结点删除,需要由两个临时指针:P1:判断指向的结点是不是要删除的结点(用于寻找);P2:始终指向P1的前面一个结点;,28,图11.19,(a),(B),29,图11.20,head,p1,(a),(b),head,p2,p1,原链表P1指向头结点,P2指向p1指向的结点。P1指向下移一个结点。,30,图11.20,head,p1,head,p2,p1,(c),(d),经判断后,第1个结点是要删除的结点,head指向第2个结点,第1个结点脱离。,经P1找到要删除的结点后使之脱离。,31,例题10,structstudent*del(structstudent*head,longnum)structstudent*p1,*p2;if(head=NULL)printf(nlistnull!n);gotoend;p1=head;while(num!=p1-num,找到了,没找到,32,11.7.7对链表的插入操作,插入结点:将一个结点插入到已有的链表中插入原则:1、插入操作不应破坏原链接关系2、插入的结点应该在它该在的位置实现方法:应该有一个插入位置的查找子过程共有三种情况:1、插入的结最小2、插入的结点最大3、插入的结在中间,33,操作分析,同删除一样,需要几个临时指针:P0:指向待插的结点;初始化:p0=数组stu;P1:指向要在P1之前插入结点;初始化:p1=head;P2:指向要在P2之后插入结点;插入操作:当符合以下条件时:p0-num与p1-num比较找位置if(p0-nump1-num),34,图11.22,head,p1,(a),p0,35,图11.22,p2,p1,(b),36,例题11,structstudentinsert(structstudent*head,structstudent*stud)structstudent*p0,*p1,*p2;p1=head;p0=stud;if(head=NULL;)head=p0;p0-next=NULL;elsewhile(p0-nump1-num),原来的链表是空表,P0指向要插的结点,使p0指向的结点作为头结点,使p2指向刚才p1指向的结点,插到原来第一个结点之前,插到p2指向的结点之后,插到最后的结点之后,链接,37,head,课堂举例:已有一个如图所示的链表;它是按结点中的整数域从小到大排序的,现在要插入一个结点,该结点中的数为10,待插入结点,此结点已插入链表,38,分析:按三种情况1、第一种情况,链表还未建成(空链表),待插入结点p实际上是第一个结点。这时必然有head=null。只要让头指针指向p就可以了。语句为,headp,head=p;p-next=null;,2、第二种情况,链表已建成,待插入结点p的数据要比头结点的数据还要小,这时有(p-num)num)当然p结点要插在head结点前。,39,head,head,p,p-next=head;head=p;,语句为,null,40,3、第三种情况,链表已建成,待插入结点p的数据比头结点的数据大,需要找到正确的插入位置。这时,可以借助两个结构指针r和g,利用循环比较来找到正确位置。然后将结点p插入到链表中正确的位置。参见下面的图示,41,head,p,g,r,说明:这种情况下,p结点已经与链表的第一个结点比较过了,所以从链表的下一个结点开始比较。138,继续比较。,42,head,p,g,r,说明:1312,继续比较。,43,head,p,g,r,null,说明:13next=p;p-next=g;,44,/结构7.c#include/预编译命令#include/内存空间分配#definenull0/定义空指针常量#defineLENsizeof(structnumST)/定义常量,表示结构长度structnumST/结构声明intnum;/整型数structnumST*next;/numST结构指针;,参考程序,45,/被调用函数insert(),两个形参分别表示链表和待插入的结点voidinsert(structnumST*phead,structnumST*p)/函数体开始structnumST*q,*r;/定义结构指针q,rif(*phead)=null)/第一种情况,链表为空*phead=p;/链表头指向preturn;/完成插入操作,返回else/链表不为空/第二种情况,p结点num值小于链表头结点的num值if(*phead)-nump-num)/将p结点插到链表头部p-next=*phead;/将p的next指针指向链表头(*phead)*phead=p;/将链表头赋值为preturn;/返回,46,/第三种情况,循环查找正确位置r=*phead;/r赋值为链表头q=(*phead)-next;/q赋值为链表的下一个结点while(q!=null)/利用循环查找正确位置/判断当前结点num是否小于p结点的numif(q-numnum)r=q;/r赋值为q,即指向q所指的结点q=q-next;/q指向链表中相邻的下一个结点else/找到了正确的位置break;/退出循环/将p结点插入正确的位置r-next=p;p-next=q;,47,/被调用函数,形参为ST结构指针,用于输出链表内容voidprint(structnumST*head)intk=0;/整型变量,用于计数structnumST*r;/声明r为ST结构指针r=head;/r赋值为head,即指向链表头while(r!=null)/当型循环,链表指针不为空则继续/循环体开始k=k+1;/计数加1printf(%d%dn,k,r-num);r=r-next;/取链表中相邻的下一个结点/循环体结束,48,voidmain()/主函数开始/函数体开始structnumST*head,*p;/ST型结构指针head=null;/分配两个ST结构的内存空间,用于构造链表head=(structnumST*)malloc(LEN);head-next=(structnumST*)malloc(LEN);/为链表中的两个结点中的num赋值为5和10head-num=5;head-next-num=10;head-next-next=null;/链表尾赋值为空/构造一个结点p,用于插入链表p=(structnumST*)malloc(LEN);p-num=8;p-next=null;insert(/调用print函数,输出链表内容/主函数结束,49,说明:函数insert()的第一个形参为structnumST*类型,即“指针的指针”。调用时送入的实参是链表头指针的地址,即程序中的charname10;charsex;charjob;unionintclass;charposition10;category;person2;main()intn,i;for(i=0;iSun、Sat最大。(4)枚举元素的值也是可以人为改变的:在定义时由程序指定。例如,如果enumweekdaysSun=,Mon,Tue,Wed,Thu,Fri,Sat;则Sun=,Mon=,从Tue=2开始,依次增。,61,例题13,/*file1.c文件1*/main()externenter-string(charstr80);externdelete-string(charstr,charch);externprint-string(charstr);charc;charstr80;enter_string(str);scanf(%c,62,续,for(i=0;ix,p-y);p=p-next;/p指向下一个结点i=i+1;/计数加1while(p!=null);/未到达链表尾部,则继续循环/主函数结束,71,用结构数组,利用键盘输入结点中的数据。重点看scanf(“%d”,结构数组,数组中的元素为结构类型的数据,如n8,/结构2.c#include/预编译命令#definenull0/定义空指针常量structTM/定义TM结构intx,y;/整型变量x,ystructTM*next;/指向TM结构的指针;,72,voidmain()/主函数/主函数开始inti,a,b;/声明整型变量i,a,b/声明TM型结构数组n8,TM结构指针head,pstructTMn8,*head,*p;for(i=1;inext=head;,head,tail,q,84,5、删结点的函数select(intmm)mm为形式参数,从1至m报数,凡报到mm者删除其所在的结点。设计两个指针p和q。一开始让q指向链表的尾部q=tail。让p指向q的下一个结点。开始时让p指向1#猴所在的结点。用一个累加器x,初始时x=0,从1#猴所在结点开始让x=x+1=1,如果mm是1的话,1#猴所在的p结点就要被删除。有三条语句printf(“被删掉的猴子号为%d号n”,p-num);q-next=p-next;free(p);,head,tail,q,p,演示,85,这里free(p)是释放p结点所占用的内存空间的语句。如果mm不是1而是3,程序会在do-while循环中,让x加两次1,q和p一起移动两次,p指向3#所在结点,q指向2#所在结点,之后仍然用上述三条语句删去3#所在的结点。,head,q,p,q,p,p,q,演示,86,这个do-while循环的退出条件是q=q-next。即当只剩下一个结点时才退出循环。当然猴王非其莫属了。这时,让头指针head指向q,head是全局变量,在主程序最后输出猴王时要用head-num。,参考程序如下:,head,q,87,#include/预编译命令#include/内存空间分配#definenull0/定义空指针常量/定义常量,表示结构长度#defineLENsizeof(structmon)structmon/结构声明intnum;/整型数,用于记录猴子号structmon*next;/mon结构指
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年矿产资源勘探工程师职业资格考试试题及答案解析
- 2025年教师资格认定考试试卷及答案解析
- 2025年健身教练员执业能力水平考核试题及答案解析
- 2025年建筑装潢工程师资格考试试题及答案解析
- 2025年机器人操作员职业技术水准测验试卷及答案解析
- 课件中强调重点的声音
- 2025年化妆品品质监督员资格考试试题及答案解析
- 课件中位数众数
- 2025年广播节目策划师资格认定考试试题及答案解析
- 2025年互联网营销师面试问题集
- 内部准驾证管理办法
- 2023年单螺杆泵的结构设计与性能分析全套图纸
- 无创正压通气护理
- GB/T 20481-2017气象干旱等级
- 风电发电机组电控系统知识-安全链部分课件
- PMBOK指南第6版中文版
- 医疗质量管理工具课件
- 急性上呼吸道感染病人的护理
- 小学教师量化考核表
- 房建监理平行检查记录表格模板(参考版)
- 计算机操作系统(第四版)-汤小丹-课后习题答案
评论
0/150
提交评论