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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

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

第七章数据结构及其应用.docx

1、第七章数据结构及其应用第七章数据结构及其应用数字,字符,声音,图像,表格等信息,均可输入计算机中进行处理。在计算机科学中,象这种能输入到计算机中并被计算机程序处理的信息,都可称为数据。 数据的基本单位是数据元素。数据之间存在有线性与非线性两种基本的逻辑结构,同时在存储结构上还有顺序和链式之分。 数据结构则是研究数据元素的逻辑结构,存储结构和与之有关的各种基本操作的一门学科。作为一个程序设计者,应当掌握好数据结构的有关知识,在解题时针对问题的特点,选择适当的数据结构,并构造算法,编出优美高效的好程序。 本章将介绍一些线性的数据结构及其基本操作。 第一节线性表“线性表”是指由有限多个类型相同的数据

2、元素组成的集合,它有以下的特点:(1)有唯一的头结点(即第一个数据元素)和尾结点(即最后一个数据元素);(2)除结点外,集合中的每个数据元素均只有一个前驱;(3)除尾结点外,集合中的每一个数据元素均只有一个后继。“线性表”是一种运用非常广范的数据结构。例一、某旅馆有100个房间,以1到100编号,第一个服务员来了,他将所有的房门都打开,第二个服务员再把所有编号是2的倍数的房门都关上,第三个服务员对编号是3的倍数的房门原来开的关上,原来关上的打开,此后的第四,五.服务员均照此办理。问第100个服务员走进后,有哪几扇门是开着的。解:Pascal程序:Program lt7_1_1;uses crt

3、;var door:array1.100 of boolean; 1到100号房门状态,false-关,true-开 i,j:integer;begin clrscr; fillchar(door,sizeof(door),true); 第一个服务员打开全部房门 for i:=2 to 100 do i表示服务员号码 for j:=1 to 100 div i do doori*j:=not doori*j; 对房号为i的倍数的房门进行相反处理 write(The code of opening door is : ); for i:=1 to 100 do if doori then wri

4、te(i, );end.分析:(1)这里用door1.100来存储1到100号房门的开关状态,即是一种线性表,其中:door1可以看成是头结点,而door100是尾结点;同时由于数组在内存中是按顺序占有一片连续的内存空间,因此这种存储结构即是顺序存储结构。 (2)这里用布尔变量true和false分别表示开和关两种状态,对某一房门进行相反处理时只要取反(not)即可,比如:若door10为false,not door10则为true。 例二、插入排序:在一个文本文件中存放的N个人的姓名,文本文件的格式为:第一行为N,以下第二至第N+1行分别是N个人的姓名(姓名不重复,由英文字母组成,长度不超过

5、10),请编一个程序,将这些姓名按字典顺序排列。解:Pascal程序:Program lt7_1_2;uses crt;type point=people; 定义结点类型 people=record name:string10; name-数据域,存放姓名 next:point; next-指针域,存放后继结点的地址 end;var head:point; n:integer; procedure init; 初始化 begin new(head);head.next:=nil; 定义头结点,初始链表为空 end; procedure insert(p:point); 将P指向的结点插入以he

6、ad开头的线性表中 var q1,q2:point; begin if head.next=nil then head.next:=p 将P指向的结点插入空链表 else begin q1:=head;q2:=q1.next; while (q2nil) and (q2.namep.name) do begin q1:=q2;q2:=q1.next; end; 查找结点p应插入的位置 q1.next:=p;p.next:=q2;将p插入q1之后q2之前 end; end; procedure work; var i:integer; fn:string; f:text; p:point; be

7、gin write(Filename:);readln(fn); assign(f,fn);reset(f); readln(f,n); for i:=1 to n do begin new(p);p.next:=nil; readln(f,p.name); insert(p); end; end; procedure print; 打印 var p:point; begin p:=head.next; while pnil do begin writeln(p.name); p:=p.next; end; end; begin clrscr; init; work; print;end.分析

8、:(1)排序有多种方法,插入排序是其中的一种,其原理同摸扑克牌类似:摸到一张牌,把它按大小顺序插入牌中,每一张都如此处理,摸完后,得到的就是一副有序的扑克牌。本题可以用插入排序求解; (2)为了减少移动数据的工作,可以采用链式存储结构。每个结点由两个域构成,数据域(用来存放姓名)和指针域(用来存放后继结点的地址)。如图A是将1,3,6,7按顺序构成一个线性链表的示意图。这样在这个有序表中插入一个5时,只需对指针进行相应地操作即可,如下图B: 头结点1 -3 -6 -7 尾结点 图 A 头结点1 -3 6 -7 尾结点 5 插入的结点 图 B练习一1、求1987乘幂的尾数: M和N是自然数,NM

9、=1,而1987M与1987N的末三位数相同,求最小的M和N。分析:(1)本题只须记录1987的乘幂的末三位数,故不必高精度计算;(2)用数组a1.n存储1987的1至n次幂的末三位数;(3)n的初始值为2,计算1987的n次幂的末三位数,并和1987的1至n-1次幂进行比较,若无相等的,则n=n+1,重复(3);否则,第一次找到相等的,即是所求的m,n值。2、一个特殊的数列: 写出两个1,然后在它们中间插入2成为121,下一步是在任意两个相邻的和数为4的数之间插入3,成为13231;再下一步又在任意两个相邻的和数为4的数之间插入4,成为1432341,.,由键盘输入N(1=N=9),求出用上

10、面方法构造出来的序列,其最后插入的数为N。分析:字符串也可以看做是一个特殊的线性表,本题初始串是11,对应N=1时的情况;然后在串中寻找相应的位置,依次插入2,3,.,K。3、求序列的第300项: 把所有3的方幂及互不相等的3的方幂和排列成一个递增序列:1,3,4,9,10,12,13,.,求这个序列的第300项。分析:本题可以用一个线性表来记录这个递增的序列,通过递推可以将整个序列构造出来。方法如下: (1)数组a存放线性表,t为尾指针,b存放3的幂,初始时t=1,b=1; (2)将b放入表尾,尾指针加1;atb;tt+1; (3)将b依次与1至t-1的元素相加,按顺序放入表尾; (4)重复

11、(2),(3),直至第300项放入表中。4、约瑟夫环(Joseph) 编号为1,2,.,N的N个人按顺时针方向围成一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值M,从第一个人开始按顺时针方向自1开始报数,报到M时停止,报M的人出列,将他的密码作为新的M值,从他在顺时针方向上的第一个人开始重新从1报数,如此下去,直至所有有人全部出列为止。试设计一个程序求出列的顺序。分析:这是一个数学游戏。N个人围成一圈,依次报数,可以用一个循环链表模拟这一过程。将链表的表尾指向表头,即形成循环链表。从某个人开始报数,报到M的人出列,也就是在在循环链表中删除相应的结点,然后依次删除完所有的结

12、点,此时链表为空,头指针与尾指针相等。在具体操作中,要注意删除头结点和尾结点时指针的处理,谨防出错。5、多项式的加法:试编程完成两个一元多项式的加法。分析:大家都知道,两个一元多项式相加实际上就是合并同类项,最后结果一般要求按字母的升幂或降幂排列,比如:(2X10+4X+1)+(3X5-4X+2)=2X10+3X5+3。那么一元多项式在计算机中如何表示呢?为了节省空间,一个元多项式一般用一个线性表表示,线性表的每一个结点包括两个域:一个用来存放系数,一个用来存放指数,比如,上面相加的两个一元多项式可以分别表示为: 2 10 4 1 1 0 3 5 -41 2 0 这样两个一元多项式相加就可以看

13、成是归并两个链表。第二节队列 在日常生活中有许多“队列“的例子,如车站售票口买票的队伍,排在前面的人先买到票离开队伍,后来的人则加入队伍的末尾等候买票;其特点是“先进先出”(First In First Out)或“后进后出”(Last In Last Out)。 “队列”是在一端插入,另一端删除的特殊的线性表。进行删除的一端称为“队首”,进行插入的一端称为“队尾”(如下图);插入也叫入队,删除则叫出队;在对队列进行操作时,一定要注意一头一尾。 出队 a1 a2 . an 入队 队头 队尾例1、有N张牌,记为1,2,.,N,应当怎样排放,才能使:打开第一张是1,然后报两张依次放在末尾;打开上面

14、一张,刚好是2,再依次打开上面一张,刚好是3;如此继续下去,直至打开最后一张是N。写一个程序解决这个问题。解:Pascal程序:Program lt7_2_1;uses crt;var a,b:array1.1000 of integer; i,j,t,h,n:integer;begin clrscr; write(N=);readln(n); for i:=1 to n do ai:=i; a1:=1;h:=2;t:=n;b1:=1; for i:=2 to n do begin for j:=1 to i do begin inc(t);at:=ah;inc(h); end; bah:=i

15、;inc(h); end; for i:=1 to n do write(bi:5);end.分析:这是一个典型队列的例子,请大家仔细体会在队列操作过程中头指针和尾指针的变化。 例2、集合的前N个元素:编一个程序,按递增次序生成集合M的最小的N个数,M的定义如下: (1)数1属于M; (2)如果X属于M,则Y=2*X+1和Z=3*1也属于M; (3)此外再没有别的数属于M。解:Pascal程序:Program lt7_2_1;uses crt;var a,b:array1.1000 of integer; x,ha,hb,t,total,n:integer;begin clrscr; writ

16、e(N=);readln(n); x:=1;a1:=1; ha:=1;hb:=1;t:=0;total:=1; while totalbhb then begin x:=bhb;inc(hb); end else begin x:=aha; if aha=bhb then inc(hb); inc(ha); end; inc(total); end;end.分析:可以用两个队列来存放Y和Z中的数,分别用数组a和数组b存放。然后递推求出第N项,方法如下: (1)令ha和hb分别为队列a和队列b的头指针,它们的尾指针为t。初始时,X=1,ha=hb=t=1; (2)将2*x+1和3*x+1分别放入

17、队列a和队列b的队尾,尾指针加1。即: at2*x+1,bt3*x+1,tt+1; (3)将队列a和队列b的头结点进行比较,可能有三种情况: (A)ahabhb (B)aha=bhb (C)aha0) or (hb0) do begin if ha0 then x:=ord(aha)-48 else x:=0; if hb0 then y:=ord(bhb)-48 else y:=0; mlm:=x+y+c; c:=mlm div 10; mlm:=mlm mod 10; inc(lm);dec(ha);dec(hb); end; if c0 then mlm:=c else dec(lm);

18、 write(a,+,b,=); for i:=lm downto 1 do write(mi);end.2、基数排序: 将278,109,063,930,589,184,505,269,008,083利用基数排序法按从小到大的顺序排列。分析:基数排序法是一种基于对关键字进行分配和收集的排序法,常用最低位优先法(Least Significant Digit first),简称LSD法。它先从最低位的关键字开始进行排序,然后对次低位关键字进行排序,依此类推,直到对最高位进行排序为止。例如本题,关键字是各位上的数码,从0到9共10个。首先,将需要排序的数放在队列A中,如图:3、有1至2N的自然数

19、,按从小到大的顺序排成一列,对这2N个数进行如下操作: (1)将这2N个数等分成A,B两组,即: A组:1,2,.,N; B组:N+1,N+2,.,2N (2)轮流从A,B两组中按顺序取数: 1,N+1,2,N+1,.,N,2N (3)再将取过的数等分为两组,并重复上述操作,直到这2N个数又按从小到大的顺序排好为止。 例如:当N=3时,操作如下: 初始序列为:1,2,3,4,5,6 (1) 1,4,2,5,3,6 (2) 1,5,4,3,2,6 (3) 1,3,5,2,4,6 (4) 1,2,3,4,5,6分析:将1至2N的自然数分成两组,用两个队列来模拟上述过程即可。4、有一个数,它的末位数

20、字是N,将N移到这个数的首位,得到的新数恰好是原数的N倍,现输入N的值,求满足条件的最小的数。第三节栈 “栈”是一种先进后出(First In Last Out)或后进先出(Last In First Out)的数据结构。日常生活中也常能见到它的实例,如压入弹夹的子弹,最先压进去的子弹最后射出,而最后压入的子弹则最先发射出来。 “栈”是一种只能在一端进行插入和删除的特殊的线性表,进行插入和删除的一端称为“栈顶”,而不动的一端称为栈底(如下图)。插入的操作也称为进栈(PUSH),删除的操作也称为出栈(POP)。 出栈 进栈 栈顶 an . a2 栈底 a1 例1、算术表达式的处理:由键盘输入一个

21、算术表达式(含有+,-,*,/,(,)运算),且运算结果为整数),编一程序求该算术表达式的值。分析:表达式的运算是程序设计中一个基本的问题,利用栈求解是一种简单易行的方法,下面介绍的是算符优先法。 比如:4+2*3-10/5 我们都知道,四则运算的法则是:(1)先乘除后加减,同级运算从左到右;(2)有括号先算括号。 因此上例的结果是8。 算符优先法需要两个栈:一个是操作数栈,用来存放操作数,记为SN;另一个是操作符栈用来存放运算符,记为SP。具体处理方法如下: (1)将SN,SP置为空栈; (2)从左开始扫描表达式,若是操作数压入SN中;若是操作符则与SP的栈顶操作符比较优先级有两种可能: (

22、a)优先级小于栈顶算符,此时从SN中弹出两个操作数,从SP弹出一个操作符,实施运算,结果压入SN的栈顶。 (b)优先级大于栈顶算符,此时将操作符压入SP中。 (3)重复操作(2)直至表达式扫描完毕,这时SP应为空栈,而SN只有一个操作数,即为最后的结果。 为了方便起见,可以将#作为表达式的结束标志,初始化时在SP的栈底压入#,并将其优先级规定为最低。下面给出的是计算4+2*3-10/5#的示意图步骤 SN SP 读入字符 说明 1 空 # 4 将4压入SN 2 4 # + 将+压入SP 3 4 # + 2 将2压入SN 4 4 2 # + * 将*压入SP 5 4 2 # + * 3 将3压入

23、SN 6 4 2 3 # + * - -的优先级小于*,因此将SN中的3,2弹出, 将SP中的*弹出,将2*3的结果压入SN中 7 4 6 # + - -的优先级小于其左边的+,因此将SN中的 4,6弹出,将SP中的+弹出,将4+6的结果压 入SN中 8 10 # - -压入SP中 9 10 # - 10 10压入SN中10 10 10 # - / 将/压入SP中11 10 10 # - / 5 将5压入SN中12 10 10 5 # - / # #优先级小于/,故SN中的10,5弹出,SP中 的/弹出,将10/5的结果压入SN中13 10 2 # - # #优先级小于-,故SN中的10,2弹

24、出,SP中 的-弹出,将10-2的结果压入SN中14 8 # # #与#相遇,运算结束,SN中的8是最后计算 的结果解:Pascal程序:Program lt7_3_1;uses crt;const number:set of char=0.9; op:set of char=+,-,*,/,(,); var expr:string; sp:array1.100 of char; sn:array1.100 of integer; t,tp,n,tn:integer; function can_cal(ch:char):boolean; begin if (ch=#) or (ch=) or

25、(sptp in *,/) and (ch in +,-) then can_cal:=true else can_cal:=false; end; procedure cal; begin case sptp of +:sntn-1:=sntn-1+sntn; -:sntn-1:=sntn-1-sntn; *:sntn-1:=sntn-1*sntn; /:sntn-1:=sntn-1 div sntn; end; dec(tn);dec(tp); end; begin clrscr; write(Expression : );readln(expr); write(expr+=); expr

26、:=expr+#; tn:=0;tp:=1;sp1:=#;t:=1; repeat if exprt in number then begin n:=0; repeat n:=n*10+ord(exprt)-48; inc(t); until not (exprt in number); inc(tn);sntn:=n; end else begin if (exprt=() or not can_cal(exprt) then begin inc(tp);sptp:=exprt;inc(t); end else if exprt=) then begin while sptp( do cal; dec(tp);inc(t); end else cal; end; until (exprt=#) and (sptp=#); writeln(sn1);end. 练习三1、假设一个算术表达式中可包含三种括号:圆括号“(”和“)”;方括号“”和“”以及花括号“”和“”,且这三种括号可按任意的次序嵌套使用,试利用栈的运算,判别给定的表达式中所含括号是否正确配对出现。分析:如果括号只有一种,比如说是“(”和“)”,则判断是否正确匹配可以

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

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