第二部分 上机实验习题
上机实验要求及规范
数据结构课程具有比较强的理论性,同时也具有较强的可应用性和实践性。在上机实验是一个重要的教学环节。一般情况下学生能够重视实验环节,对于编写程序上机练习具有一定的积极性。但是容易忽略实验的总结,忽略实验报告的撰写。对于一名大学生必须严格训练分析总结能力、书面表达能力。需要逐步培养书写科学实验报告以及科技论文的能力。拿到一个题目,一般不要急于编程。按照面向过程的程序设计思路(关于面向对象的训练将在其它后继课程中进行),正确的方法是:首先理解问题,明确给定的条件和要求解决的问题,然后按照自顶向下,逐步求精,分而治之的策略,逐一地解决子问题。具体实习步骤如下:
1.问题分析与系统结构设计
充分地分析和理解问题本身,弄清要求做什么(而不是怎么做),限制条件是什么。按照以数据结构为中心的原则划分模块,搞清数据的逻辑结构(是线性表、树还是图?),确定数据的存储结构(是顺序结构还是链表结构?)。然后设计有关操作的函数。在每个函数模块中,要综合考虑系统功能,使系统结构清晰、合理、简单和易于调试。最后写出每个模块的算法头和规格说明,列出模块之间的调用关系(可以用图表示),便完成了系统结构设计。
2.详细设计和编码
详细设计是对函数(模块)的进一步求精,用伪高级语言(如类C语言)或自然语言写出算法框架,这时不必确定很多结构和变量。
编码,即程序设计,是对详细设计结果的进一步求精,即用某种高级语言(如C/C++语言)表达出来。尽量多设一些注释语句,清晰易懂。尽量临时增加一些输出语句,便于差错矫正,在程序成功后再删去它们。
3.上机准备
熟悉高级语言用法,如C语言。熟悉机器(即操作系统),基本的常用命令。静态检查主要有两条路径,一是用一组测试数据手工执行程序(或分模块进行);二是通过阅读或给别人讲解自己的程序而深入全面地理解程序逻辑,在这个过程中再加入一些注释和断言。如果程序中逻辑概念清楚,后者将比前者有效。
4.上机调试程序
调试最好分块进行,自底向上,即先调试底层函数,必要时可以另写一个调用驱动程序,表面上的麻烦工作可以大大降低调试时所面临的复杂性,提高工作效率。
5.整理实习报告
11
在上机实开始之前要充分准备实验数据,在上机实践过程中要及时记录实验数据,在上机实践完成之后必须及时总结分析。写出实验报告。 一、实验报告的基本要求:
一般性、较小规模的上机实验题,必须遵循下列要求。养成良好的习惯。
(1) 姓名 班级 学号 日期 (2) 题目:内容叙述
(3) 程序清单(带有必要的注释)
(4) 调试报告:
实验者必须重视这一环节,否则等同于没有完成实验任务。这里可以体现个人特色、或创造性思维。具体内容包括:测试数据与运行记录;调试中遇到的主要问题,自己是如何解决的;经验和体会等。
二、实验报告的提高要求:
阶段性、较大规模的上机实验题,应该遵循下列要求。养成科学的习惯。
(1)需求和规格说明
描述问题,简述题目要解决的问题是什么。规定软件做什么。原题条件不足时补全。 (2)设计
a. 设计思想:存储结构(题目中限定的要描述);主要算法基本思想。 b. 设计表示:每个函数的头和规格说明;列出每个函数所调用和被调用的函数,也可以通过调用关系图表达。
c. 实现注释:各项功能的实现程度、在完成基本要求的基础上还有什么功能。 (3)用户手册:即使用说明。
(4)调试报告:调试过程中遇到的主要问题是如何解决的;设计的回顾、讨论和分析;
时间复杂度、空间复杂度分析;改进设想;经验和体会等。
12
实验一 复数ADT及其实现
一、实验目的
1. 了解抽象数据类型(ADT)的基本概念,及描述方法。
2. 通过对复数抽象数据类型ADT的实现,熟悉C语言语法及程序设计。为以后章节的学习打下基础。
二、实例
复数抽象数据类型ADT的描述及实现。 [复数ADT的描述]
ADT complex{
数据对象:D={ c1,c2 c1,c2∈FloatSet } 数据关系:R={
基本操作:创建一个复数 creat(a); 输出一个复数 outputc(a); 求两个复数相加之和 add(a,b); 求两个复数相减之差 sub(a,b); 求两个复数相乘之积 chengji(a,b); 等等;
} ADT complex; [复数ADT实现的源程序] #include
/* 存储表示,结构体类型的定义 */
typedef struct
{ float x; /* 实部子域 */ float y; /* 虚部的实系数子域 */ }complex; /* 全局变量的说明 */
comp a,b,a1,b1; int z;
/* 子函数的原型声明与实现 */ void creat(comp *c); void outputc(comp a); comp add(comp k,comp h);
/* 创建一个复数 */ void creat(complex *c)
13
{ float c1,c2;
printf(\输入实部real x=?\ printf(\输入虚部xvpu y=?\ (*c).x=c1; c ->y=c2; } /* creat */
/* 输出一个复数 */
void outputc(complex a)
{ printf(\ }
/* 求两个复数相加之和 */ complex add(complex k,complex h) { complex l;
l.x=k.x+h.x; l.y=k.y+h.y; return(l); } /* add */
/* 主函数 */ main()
{ colplex a,b,a1;
creat(&a); outputc(a); creat(&b); outputc(b); a1=add(a,b); outputc(a1); } /* maijn */
三、实习题
首先将上面源程序输入计算机,进行调试。运行程序,输入下列两个复数的实部域虚部,记录两个复数相加的输出结果。 原始数据:2.0 + 3.5i ,3.0 – 6.3i
然后在上面程序的基础上,增加自行设计的复数减、复数乘的两个子函数,适当补充必需的语句(例如函数原型声明、主函数中的调用等)。提示:
// 求两个复数相减之差的函数
complex sub(complex k,complex h) { ……} // 求两个复数相乘之积的函数
complex chengji(complex k,complex h){ …… }
再次调试运行程序。输入数据,记录结果,最后完成实验报告。
14
实习二 线性表
一、实验目的
1. 了解线性表的逻辑结构特性,以及这种特性在计算机内的两种存储结构。 2. 重点是线性表的基本操作在两种存储结构上的实现;其中以链表的操作为侧重点;并进一步学习结构化的程序设计方法。
二、实例
1. 线性表的顺序存储表示(结构)及实现。
阅读下列程序请注意几个问题:
(1)关于线性表的顺序存储结构的本质是:在逻辑上相邻的两个数据元素ai-1, ai,在存储地址中也是相邻的,既地址连续。不同的教材有不同的表示,有的直接采用一维数组,这种方法有些过时。有的采用含‘动态分配’一维数组的结构体,这种方法过于灵活抽象(对读者要求过高)。我们采用的是含‘静态’一维数组和线性表长的结构体: typedef struct
{ ElemType a[MAXSIZE]; /* 一维数组 子域 */ int length; /* 表长度子域 */
}SqList; /* 顺序存储的结构体类型 */
(2)本程序是一个完整的、子函数较多的源程序。目的为学生提供一个示范,提供顺序存储表示的资料,供学生参考。比如,主函数中简单“菜单设计”(do-while循环内嵌套一个 switch结构)技术。在学习数据结构的初级阶段,并不强要求学生一定使用“菜单设计”技术,同学们可以在main()函数中直接写几个简单的调用语句,就象前面的复数处理程序中的main()一样。但是随着学习的深入,尽早学会使用“菜单设计”技术,会明显提高编程和运行效率。 [源程序]
#include
#define MAXSIZE 20 /* 数组最大界限 */ typedef int ElemType; /* 数据元素类型 */ typedef struct
{ ElemType a[MAXSIZE]; /* 一维数组 子域 */ int length; /* 表长度子域 */ }SqList; /* 顺序存储的结构体类型 */ SqList a,b,c; /* 函数声明 */
void creat_list(SqList *L);
15