ImageVerifierCode 换一换
格式:DOCX , 页数:33 ,大小:153.58KB ,
资源ID:24134251      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/24134251.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(指针及线性链表.docx)为本站会员(b****2)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

指针及线性链表.docx

1、指针及线性链表指针及线性链表内容提要1 了解静态存储、动态存储的概念以及各自的优缺点;2 掌握指针类型及指针变量的含义、定义和使用方法;3 掌握线性链表的基本概念;4 掌握线性链表、循环链表、双向链表、双向循环链表的基本操作;5 能够恰当应用指针和线性链表解决一些实际问题;重点难点1. 重点:指针概念和基本操作; 线性链表的基本操作; 线性链表的应用;2. 难点:指针变量的含义、与静态变量的区别、使用方法; 线性链表的基本操作; 灵活运用线性链接表的思想解决实际问题;内容讲授一、静态存贮和动态存贮1、静态存储程序中的变量一经说明,计算机操作系统就会在内存空间中分配相应的存贮单元,其中变量名是存

2、贮单元的地址,而变量的值是存贮单元的内容,且该存贮单元自始至终都被该变量所占用,直到程序结束。如果变量是局部变量,那么在它的作用域内,一经说明也占有一定的存贮单元,直到退出其作用域为止。这样的变量,在程序执行过程中,不能随时使用随时分配存贮空间,也不能在程序执行的过程中,释放这些空间。也就是说,一旦给这些变量分配存贮空间,无论程序是否还需要使用,它们都要占用一定的存贮空间,以便给用户存贮数据。我们称具有这样特点的存贮为静态存贮,它所对应的变量称为静态变量。如字符类型、数组类型、记录类型等。这类变量的优点是存贮方便,查找容易,可以通过一个简单的公式随机存取表中的任一元素,逻辑关系上相邻的两个元素

3、在物理位置上也是相邻的,很容易找到前趋与后继元素;缺点是在线性表的长度不确定时,必须分配足够大的存储空间,经常浪费了宝贵的存储资源;而线性表的容量一经定义确定后就难以扩充;在插入和删除线性表的元素时,需要移动大量的元素,时间效率也比较差。2、动态存贮在程序执行过程中,通过向操作系统申请存贮空间或释放存贮空间的命令,达到动态管理计算机的存贮空间,以保证存贮空间的充分利用。存贮空间可以随时申请、随时释放,这样的存贮方式称为动态存贮,其变量称为动态变量。指针变量即为动态变量。动态存储所需要的空间可以是不连续的,这样有利于充分利用零散的小空间。但缺点是无法用O(1)的时间实现存取了。如何用这些零散的空

4、间存储数组这些大规模数据呢?如何表示这些数据之间的逻辑关系呢?为了表示这些物理存储单元之间的逻辑关系,对于每个数据元素来说,除了要存储它本身的信息(数据域data)外,还要存储它的直接后继元素的存储位置(指针域,一般用link或next表示)。我们往往把这两部分信息合在一起称为一个“结点node”。 N个结点链接在一起就构成了一个链表。N=0时,称为空链表。同时,为了按照逻辑顺序对链表中的元素进行各种操作,我们需要定义一个变量用来存储整个链表的第一个结点的物理位置,这个变量称为“头指针,一般用H或head表示”。也可以把头指针定义成一个结点,称为“头结点”,头结点的数据域可以不存储任何信息,也

5、可以存储线性表的长度等附加信息,头结点的指针域(头指针)存储指向第一个结点的指针,若线性表为空表,则头结点的指针域为空(NIL)。由于最后一个元素没有后继,所以线性表中最后一个结点的指针域为空(NIL)。由于此链表中的每个结点都只包含一个指针域,故称为“线性链表”或“单向链表”。二、指针类型与指针变量1指针类型和指针变量的说明Type 指针类型标识符= 基类型名; 基类型不能为文件类型Var 指针变量名: 指针类型标识符;2申请存储单元 动态申请、空间大小由指针变量的基类型决定New(指针变量名); PASCAL标准过程3指针变量的赋值 指针变量名: = NIL; 初始化,暂时不指向任何存储单

6、元 如何表示和操作指针变量?不同于简单变量(如A:=0;),PASCAL规定用“指针变量名”的形式引用指针变量(如P:=0;)。区分如下图所示: 如计算机执行下面的程序段时:new(H);H:=123;new(H);H:=234;内存示意图如下(阴影部分表示该单元已被占用):4相同基类型的指针变量之间可以进行相互赋值。如有下面的程序段,可以画出右边的示意图:var p1,p2:integer;beginnew(p1);new(p2);p1:=90;p2:=80;p1:=p2 end. 5关系运算如: if p1=p2 then while p nil do 6释放动态存储单元 dispose(

7、指针变量名);系统收回指针变量所指的内存单元另作它用,此时指针变量的值变成无定义。注意,我们应该养成一个好的习惯,就是及时释放不用的动态存储单元,很多同学使用指针变量时就知道new(p),而不知道及时dispose(p),最后造成内存空间溢出错误、出现死循环甚至死机现象。三、单向链表1、单向链表的结构由于单向链表的每个结点都有一个数据域和一个指针域,所以,每个结点都可以定义成一个记录。一般,把head称为头结点,head.next称为头指针。比如,有如下一个单向链表,如何定义这种数据结构呢? 方法如下:type pointer=nodetype; nodetype=record 嵌套定义 da

8、ta:datatype; next:pointer; end;var head,p,q,r:pointer; 2、单链表的建立、输出下面结合一个例子,给出建立并输出单向链表的程序。例1、从键盘输入若干个正整数,请按输入顺序建立一个单向链表并输出它,输入-1时表示结束(creat.?)。Program creat;type pointer=nodetype; nodetype=record data:integer; next:pointer; end;var head,p,r:pointer; r指向链表的当前最后一个结点,可以称为尾指针 x:integer;begin writeln(ple

9、ase input num(-1 is end):); read(x); new(head); 申请头结点 head:=nil; 头结点初始化 r:=head; while x-1 do 读入的数非-1 begin new(p); 则,申请一个新结点 p.data:=x; p.next:=nil; r.next:=p; 把新结点链接到前面的链表中,实际上r是p的直接前趋 r:=p; 尾指针后移一个 read(x); end; r.next:=nil; 最后一个结点的指针域赋空 readln; writeln(output: ); 输出 p:=head.next; 头指针没有数据,只要从第一个结

10、点开始就可以了 while p.nextnil do begin write(p.data:4); p:=p.next; end; write(p.data:4); 最后一个结点的数据单独输出,也可以改用REPEAT循环 readln;end. 为了充分利用空间和随时统计出链表的实际结点个数,我们经常把链表的实际结点个数存入到头结点的数据域(head.data)中,请大家改写上面的程序,并输出最后的结点个数。参考程序见programcreat.pas。3、查找“数据域满足一定条件的结点”(1)从前往后找到第一个满足条件的结点,程序如下:p:=head.next;while (p.datax)a

11、nd(p.nextnil) do p:=p.next; 找到第一个就结束if p.data = x then 找到了处理 else 输出不存在;(2)如果想找到所有满足条件的结点,则修改如下:p:=headnext;while p.nextnil do 一个一个判断beginif p.data = x then 找到一个处理一个;p:=p.nextend;4、获取第i个结点的数据域 function get(head:pointer;i:integer):integer;var p:pointer;j:integer;begin p:=head.next; j:=1; while (pnil)

12、 and (ji) do begin p:=p.next; j:=j+1;end;if (p nil) and (j=i) then writeln(p.data) else writeln(i not exsit!)end;5、插入一个结点到单链表中一般情况:s.next:=p.next;p.next:=s;特殊情况,插在表头:s.next:=head;head:=s; 插在表尾:p.next:=s;p:=s; 假设p已是表尾程序实现时,从表头开始找,是一致的。 procedure insert(head:pointer;i:integer;x:integer);插入X到第i个元素之前var

13、 p,s:pointer;j:integer;beginp:=head;j:=0;while (pnil) and (ji-1) then writeln(no this position!) else begin 插入 new(s); s.data:=x; s.next:=p.next; p.next:=s endend;6、删除单向链表中的第i个结点(如下图中数据域为“b”的结点) procedure delete(head:pointer;i:integer;);删除第i个元素var p,s:pointer;j:integer;begin p:=head; j:=0; while (p.

14、nextnil) and (ji-1) then writeln(no this position!) else begin 删除p的后继结点,假设为s s:=p.next; p.next:=p.next.next; 或p.next:=s.next dispose(s) endend;7、求单向链表的实际长度function len(head:pointer):integer; var n:integer; begin p:=head; n:=0; while p nil do begin n:=n+1; p:=p.next end; len:=n end;四、双向链表每个结点有两个指针域和若

15、干数据域,其中一个指针域指向它的直接前趋结点,一个指向它的直接后继结点。它的优点是访问、插入、删除更方便,速度也快了。实质上是以空间换时间。数据结构的定义:type pointer=nodetype; nodetype=record data:datatype; pre,next:pointer pre指向前趋,next指向后继 end;var head,p,q,r:pointer;下面给出双向链表的插入和删除过程。Procedure insert(head:pointer;i,x:integer);在双向链表的第i个结点之前插入XVar s,p:pointer;j:integer;Begin

16、 New(s); S.data:=x; P:=head;j:=0;while (p.nextnil) and (ji) do begin p:=p.next; j:=j+1 end; p指向第i个结点 if p=nil then writeln(no this position!) else begin 将结点S插入到结点P之前 s.pre:=p.pre; 1、将S的前趋指向P的前趋 p.pre:=s; 2、将S作为P的新前趋 s.next:=p; 3、将S的后继指向P p.pre.next:=s 4、将P的本来前趋结点的后继指向S end;End;Procedure delete(head:

17、pointer;i:integer);删除双向链表的第i个结点Var p:pointer;j:integer;Begin P:=head;j:=0;while (p.nextnil) and (jm1),程序判断输出最后的大王是几号?如输入:13 5输出:6换个问法:n只猴子围成一个圈,按顺时针方向报数,报到m的出圈,直到剩下一只猴子结束。输出猴子依次出圈的序号。问题分析很明显这是一个单向循环链表。数据域为猴子的编号,指针域为下一个猴子的地址。采用模拟法,从第1个猴子开始一一报数,报数实际上是计数,只要设一个计数器就可以了。当计数器由1变化到m时,删除该结点,从下一个结点开始继续计数(计数器回

18、1或者用求余运算)。直到链表中只剩下一个结点。参考程序program king;type point=node; node=record data:integer; next:point end;var m,n,s:integer; p,q,head:point;begin write(input n,m:); readln(n,m); new(head);q:=head;head.data:=1; for s:=2 to n do begin new(p);p.data:=s;q.next:=p;q:=p end; q.next:=head; s:=1;q:=head; repeat p:=

19、q.next;s:=s+1; if s mod m=0 then begin q.next:=p.next; writeln(p.data:4); dispose(p) end else q:=p until q.next=q; writeln(the king is:,q.data)end.输入输出样例输入:13 5输出: 5 10 2 8 1 9 4 13 12 3 7 11the king is:6六、线性表的综合应用例3、用单向链表实现线性表的归并操作(merge.?)问题描述已知线性表L1和L2中的数据元素按值非递减有序排列,现要求将L1和L2归并成一个新的线性表L3,使L3中的数据

20、元素仍按非递减有序排列。例如:L1=(1,3,4,5,8,9,10,11,12),L2=(2 ,4, 6, 8),则L3=(1,2,3,4,4,5,6,8,8,9,10,11,12)。注意:相同元素照算(不用删除)。标准过程procedure merge(h1,h2:pointer; var h3:pointer); 将头指针分别为h1,h2的两个单链表归并成一个新的单链表,该链表头指针为h3,注意h3要用变量型参数var p1,p2,p3:pointer; 临时用工作指针,一般不能破坏头指针begin p1:=h1.next; p2:=h2.next; h3:=h1; 新链表共用第一个链表,

21、简化,也可以另外开辟一个头结点 p3:=h3; while (p1nil) and (p2nil) do 归并 begin if p1.data=p2.data then begin 将p1结点链接到p3中去 p3.next:=p1; 指向 p3:=p1; p3后移 p1:=p1.next p1后移 end else begin 将p2结点链接到p3中去 p3.next:=p2; p3:=p2; p2:=p2.next end end;if p1nil then p3.next:=p1 将p1中剩下的结点一起链接到p3中 else p3.next:=p2 将p2中剩下的结点一起链接到p3中en

22、d;例4、一元多相式的表示和加减运算(add.?)问题描述在数学上,一个一元n次多项式Pn(x),可以按升幂写成:Pn(x)=P0 + P1X + P2X2 + P3X3 + + PnXn它由n+1个系数唯一确定。因此,在计算机里,它可以用一个线性表 P来表示: P = (P0,P1,P2,Pn)每一项的指数i隐含在系数Pi的序号里。任务 输入两行,每行为一个字符串,分别表示一个一元n次多项式Pn(x) 和一个一元m次多项式Qm(x),输出它们的和。 注意:不许输出系数为0的项、不要输出为1的系数和幂,且按幂的升序输出。输入输出样例输入:3x2+8-5x6+x 6x6+5x-3x2+8x9-2

23、0输出:-12+6x+x6+8x9数据结构方法1:按n,m分别生成n+1和m+1个结点的两个单链表,即不管系数是否为0都生成一个结点。一个指针域指向后继结点,一个数据域存放系数(不存在的项系数为0)。 浪费了很多空间,尤其是指数很高,而项数很少的情况下,浪费更严重。方法2:只生成存在的项,实际多少项就有多少结点,每个结点有2个数据域,一个存放系数,一个存放指数。 如有以下多项式P8(x)=3+8x+9x5+6x8 ,用上述两种方法表示的示意图分别如下:方法1 示意图方法2 示意图算法分析 先生成两个单链表(按插入排序的方式生成,使链表按幂升序),然后遍历两个链表,根据指数和系数进行相应的加减,

24、生成一个新链表。系数为0的结点删除掉(或不生成这种结点),输出该链表(不要输出系数中的1和幂1,但如果是常数项1,则要输出)。参考程序 program merge;type point=node; node=record coe,exp:longint; next:point; end;var h1,h2,h3:point;procedure put(h:point; coe,exp:longint);var p,newp,tmp:point;begin p:=h; while (p.nextnil)and(p.next.expexp) then begin new(newp);newp.co

25、e:=coe; newp.exp:=exp; newp.next:=p.next; p.next:=newp; end else begin p.next.coe:=p.next.coe+coe; if p.next.coe=0 then begin tmp:=p.next; p.next:=tmp.next; dispose(tmp); end; end;end;procedure readata(h:point);var s:string; i,st,coe,exp:longint; positive,yesexp:boolean;begin readln(s); s:=s+; coe:=

26、0; exp:=0; if s1=- then begin st:=2; positive:=false;end else begin st:=1; positive:=true; end; yesexp:=false; for i:=st to length(s) do if (si=+)or(si=-) then begin if not positive then coe:=-coe; put(h,coe,exp); if si=+ then positive:=true else positive:=false; coe:=0; exp:=0; yesexp:=false; end e

27、lse if si= then yesexp:=true else if si=x then begin if (i=1)or(si-1=+)or(si-1=-) then coe:=1; if si+1 then exp:=1; end else if yesexp then exp:=exp*10+ord(si)-48 else coe:=coe*10+ord(si)-48;end;procedure merge(h1,h2,h3:point);var p,tail,p1,p2,newp:point;begin tail:=h3; p1:=h1; p2:=h2; while (p1.nextnil)and(p2.nextnil) do begin if p1.next.exp=p2.next.ex

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1