数据结构与算法大平台实验指导书_第1页
数据结构与算法大平台实验指导书_第2页
数据结构与算法大平台实验指导书_第3页
数据结构与算法大平台实验指导书_第4页
数据结构与算法大平台实验指导书_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

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

文档简介

1、数据结构与算法实习指导书上海交通大学电院数据结构大平台课程组目录1. 关于实习步骤的要求和建议2. 上机实习实习一 线性结构实习二 树和二叉树实习三 查找实习四 图实习五 排序3. 实习报告样例1 关于实习步骤的要求和建议从以往的教学事先实习的经验来看,在初学阶段执行严格的实习步骤规范(包括上机操作规范),机时利用率会大大提高,有助于养成良好的程序编制风格,培养严谨、科学、高效的工作方式。在以往的教学实践中,经常发现很多学生抱怨说,化了两个小时才找出一个错误,甚至一无所获。他们不明白造成这种情况的原因,正是他们自己。有的学生不屑于按实习步骤规范去做,甚至对于实习步骤的要求和建议看都不看一遍,认

2、为那是浪费时间,这是及其害的。实习步骤规范不但可以培养科学化的工作作风,而且还能有效地避免错误。具体的步骤机规范如下:1 问题分析与系统的结构设计: 充分地分析和理解问题本身,弄清要求作什么,限制条件是什么。按照以数据结构为中心的原则划分模块,即定义数据结构及其在这些结构之上的操作,使得对数据结构的存取通过这些操作加以实现。在这个过程中,要综合考虑系统功能。要考虑系统结构清晰、合理、简单并且易于调试。最后写出每个子程序(过程或函数)的规格说明,列出它们之间的调用关系,可以使用调用关系图表示则更加清晰,这样便完成了系统结构设计。2 详细设计和编码详细设计的目的是对子程序(过程或函数)的进一步求精

3、。用 IF 、WHILE和赋值语句等,以及自然语言写出算法的框架。利用自然语言的目的是避免陷入细节。在编码时,可以对详细设计的结果进一步求精,用高级语言表示出来。程序的每一行最好不超过 60 个字符。每个子程序(或过程、函数)通常不要太长,以 40 行为宜。子程序(或过程、函数)包含的程序行数太多,易于造成理解的困难。控制 IF 、WHILE 等语句的连续嵌套的深度应加以控制。程序的目的性必须明确。对每一段程序完成的作用,除非常明显的除外(如:x = x + 1; 注释为 x 加 1,没有什么意义),都应加以注释。这会对程序的调试提供很多方便。另外,根据情况可以设立若干调试点,即输出若干信息,

4、用于验证和你的设想是否一致。另外,对于输入输出语句,必须对它们的作用加以说明。否则,在调试程序时,无法了解系统需要输入什么,系统输出的又是什么。程序的书写,必须按照一定的规范,如保留字小写时涂黑等等。3 上机准备和静态检查上机准备:l 高级语言文本l 熟悉机器的用户手册,熟悉常用的命令。l 准备调试的工具,考虑调试方案。如果机器上没有现成的调试工具可供利用,可以自己先设计一些以供使用。l 静态检查自己用一组数据手动执行程序;或同同学一起阅读自己的程序,以全面地了解该程序的逻辑。4 上机调试程序自底向上,先调试底层模块,再调试上层模块。最后,整个程序进行联调。调试正确后将源程序和运行结果加以列印

5、输出。5 实习报告的整理l 需求及规格说明问题描述,求解的问题是什么。l 设计:设计思想:存储结构、主要的算法思想。设计表示:子程序(过程或函数)的规格说明,通过调用关系图表 示它们之间的调用关系。实现注释:详细设计表示:主要算法的框架。l 用户手册:使用说明。l 调试报告:问题是如何解决的,讨论与分析、改进设想、经验与体会、时空复杂度等。l 附录源程序清单和结果:源程序必须有注释,以及必要的测试数据和运行结果数据。提倡用英文描述。l 实验报告要求:在程序开发过程中,逐步形成各种必要的文档及资料。可以写在实验报告纸上,或以电子文档的形式进行书写。2 上机实习 l 以下的实习题目配合课程的进度,

6、请同学们务必自己完成。为了锻炼自己的应用各种不同的数据结构的能力,尽可能的多作一些题目是非常必要的。在完成各种不同题目的过程中,对各种算法的时、空复杂性的分析,将帮助您在更高的角度解决各种应用问题。l 为了减轻同学的负担,我们对同学的实习报告进行了精简。本实习报告中的题目分以下几种类型:1、 实习题:必须按照实习报告的规范完成。每个实习的第一题都是实习题,必须编写详细的实习报告。实习报告的书写方法,请参阅本指导书的第 3 部分:实习报告的样例。2、 作业题:同样必须完成。只需交代清楚题目的解法,辅以求解程序和注释,使得别人能够看懂你的算法和程序即可。不必象实习题那样书写完整的实习报告。3、 选

7、作题:鼓励同学选作的题目,尤其是学有余力的同学。以下为各次实习作业:实习一 线性结构1、(实习题) 请写出计算两个以 单链接表表示的多项式相乘的程序。 2、(作业题) 已知两个单链表 A 和 B 分别表示两个集合,其元素递增排列。请编写程序求集合 A 和 B 的交集 C = AÇB,要求单链表C按其元素递增排列,并利用原表(即表A和表B)的结点空间存放表C。3、(作业题) 假设有 二 个栈共同使用一块顺序存储的空间,为简单起见可设为共同使用数组 int a200。它们的栈底分别设在数组的两端,而栈顶指针在进行插 入操作时,向中间方向移动。请给出进出栈的程序。4、(选作题) 将具有头结

8、点的单链表的所有指针全部进行倒向。要求使用的额外空间只能为 O(1),时间代价只能为O(n),其中 n 为结点个数。 注意:如下图1所示的单链表,倒向之后将如图2所示。head ABCDhead ABCD图 1、倒向之前的单链表 图 2、倒向之后的单链表实习二 树和二叉树1、(实习题) 请编写一个程序,确定二叉树的特征。如:每个节点的层次,从根到该节点的枝长(路径长度),子孙的个数及祖先的个数。每个节点在前序、中序、后序中的访问的序号。2、(作业题) 设二叉树的结点的数据场之值仅为一大写英文字母。其前序和中序的遍历结果(打印结点的数据场之值)分别保存在字符串数组 preorderN 及 ino

9、rderN之中,其中 N 未常数。请设计程序以标准形式形式存储保存该二叉树。3、(作业题) 设树的根结点的层号为1,而其他各层上的结点的层号比其父结点的层号大 1。另外设该树中的结点的数据场之值为正整数。这样数对( Ik,Wk)就表示了该树中的结点的层号和其数据场之值。从键盘上依次输入 m 个数对,如:( I1,W1),( I2,W2),( Im,Wm);这些数对是按照结点的前序序列给出的。注意这是用 层号 前序 表示一棵树的方法。如:(1,A), (2,B), (2,C), (3,E), (4,G), (3,F), (2,D), (3,X), (3,Y), (3,Z);它所表示的树如图 3

10、所示。请编写程序,以标准形式存储这棵树。为了简单起见,可设这棵树上的结点的度数最大为 3,结点的存储形式为:dataparentson1 son2 son3其中:data 域为结点的数据场,parent 域为结点的父亲结点的地址,son1,son2,son3分别给出结点的三个儿子的地址。ACDBZYXFEG 图 3 、 一课三次树4、(选作题) 用标准形式给出了一棵度为三的树(每个结点包含数据场、指向儿子节点的指针场,可参阅上题 )。设该三次树的数据场的值为一个字符,请编写一个程序,以树的两维形式表示打印节点的值。 注意:图 3 即为树的二维表示形式。在实现时,为了方便可用打点的方法代替直线。

11、实习三 查找1、(实习题) 从键盘上输 入一串正整数, 最后输入1作为输入结束的标志。如输入的序列为:2,5,7,23,48,96,-1。请以这些正整数的值作为二叉排序树中的结点的数据场之值,建立一棵二叉排序树。注意:请采用动态存储方法保存这棵二叉排序树,事先并未知道该二叉排序树中的结点的个数。2、 (作业题) 已知一棵排序二叉树,树中结点的形式为:data info left right其中,data 给出结点的数据场,info 给出本结点的左子树中的结点总数,left和 right 分别给出本结点的左儿子和右儿子的地址。数据场data 和info的类型皆为 int。又已知该二叉排序树的根结

12、点的地址为 root。请设计二个函数,分别实现下述功能:1 按递增序找出该二叉排序树中的第 i 个小的结点。2 插入数据场之值为 x 的结点,并仍应保持该二叉排序树的性质不 变。3、 (作业题) 已知一棵二叉排序树,其根结点的地址为 root。请编写一个程序,构造出一棵具有相同结点的完全二叉树,且它同样是二叉排序树。4、(选作题)在平衡的排序二叉树的中,试编写删除具有给定关键字的结点的函数。 实习四 图1、(实习题) 以数偶的形式依次从键盘上输入一串数据。如:(A,B)为从起始结点(其数据场之值为一大写的英文字母 A ),到终止结点(其数据场之值为一大写的英文字母 B)的无向边。最后输入(Z,

13、Z)表示输入结束。请用无向图的邻接多重表存储该无向图,并注意一定要使用动态存储结构。2、(作业题) 已知一以动态存储结构形式存储的,以邻接多重表表示的无向图。请用KRUSKAL算法求出它的最小代价生成树。3、(作业题) 已知一以邻接矩阵形式存储的 AOV 图。请求出它的所有的合理的拓扑排序的序列。4 、(选作题) 已 知 一 以 动 态 存 储 结 构 形 式 存 储 的, 以 邻 接 表 表 示 的 有 向 图。 请 求 出 它 的 强 连 通 分 量。 实习五 排序1、(实习题)编写一个程 序,查找未排序序列中第K个最小的元素,要求使用类似快速排序的算法。并简单讨论一下在最坏情况下,所耗费

14、的时间。2、(作业题)奇偶排序。将被排序的序列进行如下操作。反复进行直至不再进行交换为止。第一遍:比较xi同xi+1(对所有奇数i);第二遍:比较xi同xi+1(对所有偶数i);每次比较,如果xi>xi+1则交换之,继续这样做,直至不交换为止。该方法的结束条件如何?写一个C+程序加以实现。3、(作业题)已知整数数组 int an。其中:a1,a2, an-2,an-1 已经被整理成为最小化堆,注意此处未使用a 0 。现在要求删除该最小化堆中的任意一个结点,如:a i ( 注意:1 i n-1 );而且删除a i 之后 a1,a2, an-2 仍然要被整理成最小化堆。请设计一个函数加以完成

15、,并且程序的时间复杂性必须为O(log2n)。4 、(选作题)已知整数数组 int an。其中,a1,a2, ,an1 已被整理成最小化堆。在将a1,a2, ,an-1,an 整理成最小堆时,可分两步进行:1、先找出an之值的插入位置; 2、再进行适当的数据移动即可。现仅仅考虑第一步,找出an之值的插入位置。请设计一个程序加以完成。注意该程序的时间复杂性必须为O(log2log2n),并加以证明。3、实习报告样例一、实习题:约瑟夫(Josephus)问题:设有n 个人围成一个圆圈,任意给定一个正整数m,从第一个人开始顺时针计数,计到第m个人,将其从圆圈中除去。然后再从下一个人开始,周而复始,直

16、到圆圈中只剩一个人为止,那么剩下的那个人就是赢家。1需求分析和说明分析约瑟夫问题:n个人围成圈,从第一个人开始,数到第m个人,删除并以下一个人开始进行第二轮操作,直到最后一个人作为优胜者。例如n=6, m=3, 处理过程下图。2设计n个人围圈,形成线性关系;处理为逐个删除,故用链式结构合适;又人员围成圆圈,所以此链式结构采用循环方式较好;排号按照一个方向进行,故数据结构采用带头结点的单向循环链表。假设人员以首次的编号命名,对每个人员采用编号和姓名加以描述。存储结构:struct person /定义人员信息,包括序号和姓名intno;char name10;/circlinklist.h单向循

17、环链表类template <class ElemType> class CircLinkList CircLinkListNode<ElemType> *head, *tail;/指向表头结头和尾结点CircLinkListNode<ElemType> *currPtr; /指向当前工作结点CircLinkListNode<ElemType> *prevPtr; /指向当前工作结点的前一结点int size;/表中元素的个数int position;/表中当前元素所在的元素序号(位置)public: CircLinkList ( );/构造函数

18、CircLinkList ( ); /析构函数void Clear ( ); /链表置空int Length ( ) constreturn size;; /求链表长度bool IsEmpty ( ) constreturn (size=0);;/判断链表是否空bool IsEnd ( ) constreturn (currPtr=tail);;/当前结点是否是尾结点int CurrentPosition() constreturn position; /返回当前结点的序号ElemType Data ( ) const; /返回当前指针所指的结点中的元素值void GoNext ( );/将当

19、前指针指向当前结点后面的一个结点void Reset(int pos);/将当前指针指向序号为pos的结点CircLinkListNode<ElemType> *Find ( ElemType e ); /查找从当前结点起第一个元素值为e的结点/各种位置上的插入操作void InsertFront (const ElemType e );/在首结点位置上插入元素值为e的新结点void InsertTail (const ElemType e );/在尾结点之后插入元素值为e的新结点,使其成为新的尾结点void InsertAt (const ElemType e );/在当前结点位

20、置上插入元素值为e的新结点, /原来的当前结点成为其后一个结点void InsertAfter (const ElemType e );/在当前结点之后插入元素值为e的新结点 ElemType RemoveFront( );/删除首结点,并返回其元素值ElemType RemoveAt( );/删除当前结点,并返回其元素值;算法思想:声明一个person类型的单向循环链表。从键盘顺序输入n个人的姓名, 建立约瑟夫环。计数并逐个读取并删除第m个人,直到链表为空,其中最后一个被读出的即优胜者。调用关系:程序任务简单,故设计在一个main()函数内,只设计类成员函数的调用,无另外的子程序或函数。算法

21、实现框架:3用户手册:运行程序,按照屏幕提示分别输入圈内人数n,正整数m和n个人的姓名,之后屏幕将显示按照输入次序排好的人员被逐个删除的次序,最后显示最后的出优胜者。4调试报告:时间复杂度分析:该算法在建立时的时间复杂度为O(n), 删除时时间耗费在逐个数元素上,按照第m个删除的原则,不妨将n个元素分成若干组,每组m个人,n个人最多分n/m+1组。扩展最后一组,使其也是m个人,对组内元素从1到m排号,每组排号为m的只数到一次便被删除;第二圈数每组排号为1的被删除,每个元素数过2次;第三圈数每组排号为2的被删除,每个元素数过3次;最后,第m圈, 每组排号为m-1的被删除,每个元素数过m次;故总删

22、除总的时间为:(n/m+1)(1+2+3+m)=m(m+1)(n/m+1)/2,时间复杂度为:O(n*m);缩小最后一组,使其是0个人,同上可得删除总的时间为:(n/m)(1+2+3+m)=m(m+1)(n/m)/2,时间复杂度也为:O(n*m);综合建立和删除,算法时间复杂度为:O(n*m)算法改进思路:在对元素数数删除过程中,总是要去判断是否是头结点并绕过它,可以改进一下,去掉头结点,由此看来,并非链式结构带有头结点都有益处。改进后性能可以提高,但时间复杂度依然为:O(n*m)5附录源程序清单/josephusRing.cpp#include <iostream.h>#incl

23、ude "circlinklist.h"struct person /定义人员信息,包括序号和姓名intno;char name10;void main() CircLinkList<person> josephusRing;/声称一个单向循环链表类对象person temp;int i;int n, m;/共有n个人,计数到 m 删除/从键盘输入总人数ncout<<"Input the number of people:"cin>>n;cout<<endl;/从键盘输入计数标准mcout<<&

24、quot;Input count number:"cin>>m;cout<<endl;/顺序输入n个人的姓名, 建立约瑟夫环cout<<"Input every person's name:"<<endl;for (i=1; i<=n; i+) cin>>;/输入姓名temp.no=i;/将输入次序作为人员编号josephusRing.InsertTail(temp);/将新来人员信息加入到链表尾部/计数并逐个删除第m个人,直到链表为空josephusRing.Reset(1); /当前结点设置为首结点i=0;cout<<"Deleted order: "<<endl;while (!josephusRi

温馨提示

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

评论

0/150

提交评论