c语言的链表ppt,C语言链表详解ppt.ppt

62e50291a81fc54b507f33cb80033297.gif C语言链表详解ppt.ppt

(91页)

db7d09970c915636e59454545b8aca9d.gif

本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦!

11.90 积分

*第十一章 链表链表详解珍藏版*例:跳马。依下图将每一步跳马之后的位置(x,y)放到一个“结点”里,再用“链子穿起来”,形成一条链,相邻两结点间用一个指针将两者连到一起。结构的概念与应用*依上图有7个结点(x1,y1)(x2,y2)(x6,y6)(x7,y7)为了表示这种既有数据又有指针的情况,引入结构这种数据类型。*11.7 用指针处理链表链表是程序设计中一种重要的动态数据结构,它是动态地进行存储分配的一种结构。动态性体现为:链表中的元素个数可以根据需要增加和减少,不像数组,在声明之后就固定不变;元素的位置可以变化,即可以从某个位置删除,然后再插入到一个新的地方;*1249 A1356 B1475 C1021 DNull1、链表中的元素称为“结点”,每个结点包括两个域:数据域和指针域;2、单向链表通常由一个头指针(head),用于指向链表头;3、单向链表有一个尾结点,该结点的指针部分指向一个空结点(NULL) 。Head 1249 1356 1475 1021结点里的指针是存放下一个结点的地址*链表中结点的定义链表是由结点构成的, 关键是定义结点;链表的结点定义打破了先定义再使用的限制,即可以用自己定义自己;递归函数的定义也违反了先定义再使用;这是C语言程序设计上的两大特例* 链表的基本操作对链表的基本操作有:(1)创建链表是指,从无到有地建立起一个链表,即往空链表中依次插入若干结点,并保持结点之间的前驱和后继关系。(2)检索操作是指,按给定的结点索引号或检索条件,查找某个结点。如果找到指定的结点,则称为检索成功;否则,称为检索失败。(3)插入操作是指,在结点ki-1与ki之间插入一个新的结点k’,使线性表的长度增1,且ki-1与ki的逻辑关系发生如下变化:插入前,ki-1是ki的前驱,ki是ki-1的后继;插入后,新插入的结点k’成为ki-1的后继、ki的前驱.*(4)删除操作是指,删除结点ki,使线性表的长度减1,且ki-1、ki和ki+1之间的逻辑关系发生如下变化:删除前,ki是ki+1的前驱、ki-1的后继;删除后,ki-1成为ki+1的前驱,ki+1成为ki-1的后继.(5)打印输出*一个指针类型的成员既可指向其它类型的结构体数据,也可以指向自己所在的结构体类型的数据9910189.599103909910785numScorenextnext是struct student类型中的一个成员,它又指向struct student类型的数据。换名话说:next存放下一个结点的地址*11.7.2 简单链表#define NULL 0struct student{ long num; float score; struct student *next; };main(){ struct student a, b, c, *head, *p; a.num=99101; a.score=89.5; b. num=99103; b.score=90; c.num=99107 ; c.score=85; head=&a; a.next=&b; b.next=&c; c.next=NULL; p=head; do { printf("%ld %5.1f\n",p->num,p->score); p=p->next; }while(p!=NULL); }例11.7建立和输出一个简单链表各结点在程序中定义,不是临时开辟的,始终占有内容不放,这种链表称为“静态链表”* 11.7.3 处理动态链表所需的函数C 语言使用系统函数动态开辟和释放存储单元1.malloc 函数 函数原形:void *malloc(unsigned int size);作用:在内存的动态存储区中分配 一个 长度为size的连续空间。返回值:是一个指向分配域起始地址的指针(基本类型void)。执行失败:返回NULL*函数原形:void *calloc(unsigned n,unsigned size);作用:在内存动态区中分配 n个 长度为size的连续空间。函数返回值:指向分配域起始地址的指针执行失败:返回null主要用途:为一维数组开辟动态存储空间。n 为数组元素个数,每个元素长度为size2. calloc 函数*3. free 函数函数原形: void free(void *p);作用:释放由 p 指向的内存区。P:是最近一次调用 calloc 或 malloc 函数时返回的值。free 函数无返回值动态分配的存储单元在用完后一定要释放,否则内存会因申请空间过多引起资源不足而出现故障。*结点的动态分配ANSI C 的三个函数(头文件 malloc.h) void *malloc(unsigned int size)void *calloc(unsigned n, unsigned size)void free(void *p)C++ 的两个函数new 类型(初值) delete [ ] 指针变量 /*[ ] 表示释放数组,可有可无)*/使用 new 的优点:可以通过对象的大小直接分配,而不管对象的具体长度是多少(p340 例14.10)*11.7.4 建立动态链表基本方法: 三个结点(头结点head、尾结点 NULL 和待插入结点 P)第一步:定义头结点head、尾结点 p2 和待插入结点p1,待插入的结点数据部分初始化;第二步:该结点被头结点、尾结点同时指向。P1=p2=(struct student*)malloc(LEN);头指针部分为空,head=NULL; 第三步:重复申请待插入结点空间,对该结点的数据部分赋值(或输入值),将该结点插入在最前面,或者最后面(书上在尾部插入). P2->next=P1; P2=P1; 最后:P2->next=NULL;*head,*p1,*p2使用malloc(LEN)P2->next=NULL;*11.7.4 建立动态链表9910189.5headP1p21.任务是开辟结点和输入数据2.并建立前后相链的关系待插入的结点p1数据部分初始化,该结点被头结点head、尾结点p2同时指向.*图11.149910189.5headp29910390p19910189.5headp29910390p1(a)(b)p1重复申请待插入结点空间,对该结点的数据部分赋值(或输入值)P2->next 指向p1新开辟的结点。*图11.14head9910189.5p1p29910390(c)P2指向新结点p2=p1*图11.159910189.59910189.5p29910785p1head9910189.59910189.5p29910785p1head(a)(b)* 图11.16 99103909910785p200。省略部分。环链表例:猴子选大王。 n只猴子围成一圈,顺时针方向从1到n编号。之后从1号开始沿顺时针方向让猴子从1,2,…,m依次报数,凡报到m的猴子,都让其出圈,取消候选资格。然后不停地按顺时针方向逐一让报出m者出圈,最后剩下一个就是猴王。*起始位置猴 王123456783615284猴子被淘汰的顺序演示:n=8, m=3*说明: 如图1所示有8只猴子围成一圈,m=3。从1#猴的位置开始,顺时针1至3报数,第一个出圈的是3#;第二个出圈的是6#,第3个出圈的是1#;第4个出圈的是5#;第5个是2#,第6个是8#;第7个是4#。最后剩下一个是7#,它就是猴王。我们用循环链表来模拟这个选择过程。*1、定义一个名为mon的结构 struct mon { int num; // 整数,表示猴子的编号 struct mon *next; // 指针,指向相邻的下一只猴子 }2、将链表的头指针head定义为全局变量。 struct mon*head;3、主函数 用键盘输入猴子数n,输入数m,调用函数create建立一个循环链表,模拟众猴围成一圈的情况。该函数的实参为n。调用函数select,模拟1至m报数,让n-1只猴子逐一出列的过程。即在具有n个结点的循环链表按报数m删除结点的过程。该函数的实参为m,最后输出猴王的编号。*4、建立循环链表的函数create(int nn) 其中nn为形式参数。要从编号1到编号nn。思路是(1)先做第1个结点,让其中的数据域p->num赋值为1,让指针域赋值为null。之后让链头指针head指向第1个结点。利用指针q记住这个结点,以便让指针p去生成下面的结点。(2)利用一个计数循环结构,做出第2个结点到第nn个结点。并将相邻结点一个接一个链接到一起。(3)最后一个结点要和头结点用下一语句链接到一起 tail = q; tail->next = head;headtailq*5、删结点的函数select(int mm) 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);1head28tailqp演示*这里free(p)是释放p结点所占用的内存空间的语句。如果mm不是1而是3,程序会在do-while循环中,让x加两次1,q和p一起移动两次,p指向3#所在结点,q指向2#所在结点,之后仍然用上述三条语句删去3#所在的结点。1head28qp34qppq演示*这个do-while循环的退出条件是q==q->next。即当只剩下一个结点时才退出循环。当然猴王非其莫属了。这时,让头指针head指向q,head是全局变量,在主程序最后输出猴王时要用head->num。参考程序如下:7headq*#include // 预编译命令#include // 内存空间分配#define null 0 // 定义空指针常量// 定义常量,表示结构长度#define LEN sizeof(struct mon)struct mon // 结构声明{ int num; // 整型数,用于记录猴子号 struct mon *next; // mon结构指针};struct mon *head, *tail; // mon结构指针,全局变量*void create(int nn) // 被调用函数{ // 函数体开始 int i; // 整型变量i,用于计数 struct mon *p,*q; // 声明mon结构指针p,q // 为p分配内存空间 p=(struct mon *) malloc(LEN); p->num=1; // 初始化p结点num域为1 p->next=null; // 初始化p结点next域为空 head=p; // 链表头指针head赋值为p q=p; // q赋值为p* for(i=2;inum=i; // 初始化p结点num域为i,表示猴子号 q->next=p; // 将p结点加到链表尾部 q=p; // 让q指向链表尾部结点 p->next=null; // 链表尾部指向空 } // 循环体结束 tail = q; // 链表尾 tail->next=head; // 链表尾部指向链表头, // 形成循环链表} // 函数体结束*// 被调用函数select,mm表示结点删除间隔void select(int mm){ // 函数体开始 int x=0; // 声明整型值x,并初始化为0 struct mon *p,*q; // 声明结构指针p,q q=tail; // q赋值为tail,指向循环链表尾部 do // 直到型循环,用于循环删除指定间隔的结点 { // 循环体开始 p=q->next; // p赋值为q相邻的下一个结点 x=x+1; // x加1 if(x % mm==0) // x是否整除mm, { // 表示是否跳过指定间隔 // 输出被删掉的猴子号 printf("被删掉的猴子号为%d号\n",p->num); q->next=p->next; // 删除此结点 free(p); // 释放空间 } else q=p; // q指向相邻的下一个结点p }while(q!=q->next); // 剩余结点数不为1,则继续循环 head = q; // head指向结点q,q为链表中剩余一个结点} // 函数体结束*void main() // 主函数开始{ // 函数体开始 int n,m; // 声明整型变量n,m head = null; // 初始化head为空 printf("请输入猴子数\n"); // 提示信息 scanf("%d",&n); // 输入待插入结点数据 printf("请输入间隔m\n"); // 提示信息 scanf("%d",&m); // 输入间隔 create(n); // 调用函数create建立循环链表 select(m); // 调用函数select,找出剩下的猴子 printf("猴王是%d号\n",head->num); // 输出猴王} // 函数体结束 关 键 词: c语言 ppt 链表 详解

524d6daf746efaa52c3c71bbfe7ba172.gif  天天文库所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值