数据结构课程实验指导书
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《数据结构》实验指导书
第一部分前言
一、实验的目的
《数据结构》是计算机学科一门重要的专业基础课程,也是计算机学科的一门核心课程。
本课程的另一重要教学目的是训练学生进行复杂程序设计的技能和培养良好程序设计的习惯,要做到这一点,上机实习是必须的。
数据结构实验是对学生的一种全面综合训练,是与课堂听讲、自学和练习相辅相成的必不可少的一个教学环节。
通常,实验课题中的问题比平时的习题复杂得多,也更接近实际。
实验着眼于原理与应用的结合点,使学生学会如何把书上学到的知识用于解决实际问题,训练学生实际动手进行程序设计和调试程序的能力,加深对数据结构相关概念和算法的理解。
通过完成本实验课程的实验,学生应学会并掌握本课程的基本和重点知识,深刻理解逻辑结构、物理结构和算法设计之间的关系,初步学会算法分析的方法,并能在一定范围内运用所掌握的分析方法进行算法分析,培养软件工作所需要的动手能力和作为一个软件工作者所应具备的科学工作方法和作风。
二、实验前的准备工作
1.每个学生需配备一台计算机,操作系统需Windows2000/XP以上版本,软件需Visual C++6.0以上版本。
2.实验前要求学生按实验要求编写好相关实验程序,准备上机调试运行。
三、实验的步骤
(一)建立一个文件夹,如“数据结构”,用来存放自己的所有实验程序,在该文件夹中建立子目录用来存放每个项目(一个子目录一个项目),如“顺序表”,项目中需要的所有文件都存在该文件夹中。
(二)新建一个项目文件
1.双击Visual C++ 6.0快捷图标,进入Visual C++ 6.0集成开发环境;或
者点击“开始”→“程序”→“Microsoft Visual Studio 6.0”→“Microsoft Visual C++ 6.0”进入Visual C++ 6.0集成开发环境。
2.单击“File”菜单,选择“New”命令
3.创建一个项目文件并保存在项目所在文件夹中;
3. 创建源程序文件并保存在项目所在文件夹中;
4.输入源程序;
5.单击“保存”按钮保存源程序。
(三)编译、构建和运行
1.编译:“编译Compile”→”编译”或者按ctrl-F7。
在改正语法错误(包括“错误(error)”和“警告(warning)”)后,程序经过连接(link)就得到可执行的目标程序。
2.构建:“编译Compile”→“构建Build”或者按F7
3.运行:“编译Compile”→”运行Run”或者按 Ctrl+F5。
(四)运行错误处理
通常所说的运行错误有两种:一种是逻辑错误,即程序的实际运行结果和对程序结果的期望不符;另一种是程序设计上的错误,但他躲过了编译程序和连接程序的检查,通常表现为突然死机、自行热启动或者输出信息混乱。
运行结果不对,大多属于逻辑错误。
一种逻辑错误是由于在设计程序的算法时考虑欠周到引起的,如对边界和特殊情况未作妥善处理,另一种常见的逻辑错误是由于程序输入时的打字错误造成的,例如将判断条件中的“〉=”误输入为“〉”,将相等判断“= =”误输入为赋值号“=”等。
含有这类错误的程序在运行时出现的故障现象多种多样,而且通常很难与错误的原因联系起来。
相对于编译和连接错误来说,运行错误的查找和判断更为困难。
编译和连接错误分别由编译程序和连接程序检查,尽管有时它们报告的出错信息和错误的实际原因之间有一些差距,但总还可以作为查错时的一种参考。
而运行错误就不同了,很少或根本没有提示信息,只能靠程序员的经验来判断错误的性质和位置。
一种逻辑错误是由于在设计程序的算法时考虑欠周到引起的,如对边界和特殊情况未作妥善处理。
输入的数据中包含错误或者输入数据的格式不符合要求当然也会影响到程序的运行结果。
对这类错误往往需要仔细检查和分析才能发现。
可以采用以下办法:
1.将程序与流程图仔细对照,如果流程图是正确的,程序写错了,是很容易发现的。
例如,复合语句忘记写花括弧,只要一对照流程图就能很快发现。
2.如果实在找不到错误,可以采用“分段检查”的方法。
在程序不同的位置设几个printf函数语句,输出有关变量的值,逐段往下检查。
直到找到在某一段中数据不对为止。
这时就已经把错误局限在这一段中了。
不断减小“查错区”,就能发现错误所在。
3.也可以用“条件编译”命令进行程序调试(在程序调试阶段,若干printf 函数语句就要进行编译并执行。
当调试完毕,这些语句不用再编译了,也不再被执行了)。
这种方法可以不必一一去掉printf函数语句,以提高效率。
4.如果在程序中没有发现问题,就要检查流程图有无错误,即算法有无问题。
如有则改正之,接着修改程序。
5.系统还提供debug(调试)工具,跟踪程序并给出相应信息,使用更为方便,请查阅有关手册。
总之,程序调试是一项细致深入的工作,需要下功夫,动脑子,善于积累经验。
在程序调试过程中往往反映出一个人的水平,经验和态度。
上机调试程序的目的决不是为了“验证程序的正确”,而是“掌握调试的方法和技术”,要学会自己找问题,这样慢慢自己就会写出错误较少的实用程序。
(四)保存,关闭,下次打开。
1.保存:“文件”→“保存工作区Save Workspace”
2.关闭:“文件”→“关闭工作区Close Workspace”
3.下次打开
(1)“文件”→“打开工作区Open Workspace” 顺序表.dsw
(2)“文件”→“最近工作区Recent Workspace”
四、实验的要求
(一)要求严格按照软件工程的开发步骤来完成实验
1.问题分析和任务定义
2.数据类型和系统设计
3.编码实现和静态检查
4.上机准备和上机调试
5.总结和整理实验报告
(二)写好实验报告
实验报告的开头应给出题目、班级、姓名、学号和完成日期,实验报告的撰写应包括以下内容:
1.实验目的。
2.实验内容。
3.程序清单。
4.运行结果。
5.对运行结果的分析,以及本次实验取得的经验。
五、实验任务与时间安排
六、教材
杨晓光编著·《数据结构实例教程》·清华大学出版社·北京交通大学出版社:
北京·2008年第1版。
第二部分实验内容
实验一线性表及应用
一、实验目的
1.掌握线性表的基本操作,插入、删除、查找以及线性表合并等运算在顺
序存储结构和链式存储结构上的运算;
2.运用线性表解决线性结构问题。
二、实验内容和步骤
1.建立一个类型为整型顺序表的头文件和基本操作,特别是初始化操作、插入操作、删除操作、查找操作、遍历操作等。
2.创建有10个元素的线性顺序表,验证插入、删除、查找操作的结果,将源程序以实验2-1为文件名保存在自己的文件夹里面
3.建立一个类型为整型链接表的头文件和基本操作,特别是初始化操作、插入操作、删除操作、查找操作、遍历操作等。
4.创建有10个元素的线性链接表,验证插入、删除、查找操作的结果,将源程序以实验2-2为文件名保存在自己的文件夹里面。
选作:
5.将事先建立好的顺序表La和Lb合并成一个顺序表。
要求:将Lb中不同于La中的元素插入到La的最后面。
将源程序以实验2-3为文件名保存在自己的文件夹里面。
6.在上述实验的基础上分别实现类型为结构体的线性顺序表和链接表的基本操作及其有序表的合并操作。
三、实验提示
(一)顺序表的基本操作实现实验
1、建立头文件SqList.h,完成顺序表的类型定义及基本操作。
/*********************************/
/*顺序表的头文件,文件名SqList.h */
/*********************************/
#include <stdio.h>
#define LISTSIZE 100 /*表空间大小可根据实际需要而定,这里假设为100*/
typedef int DataType; /* DataType可以是任何相应的数据类型,如struct等 */
typedef struct{
DataType items[LISTSIZE];// 存放顺序表元素
int length; // 存放顺序表的长度
}SqList; // 顺序表的类型定义
/*算法2-1初始化顺序表*/
int InitList(SqList *L)
{
L->length=0;
return 1;
}
/*算法2-2求顺序表长*/
int ListLength(SqList L)
{
return L.length;
}
/*算法2-3判断顺序表是否为空*/
int ListEmpty(SqList L)
{
if(L.length<=0)
return 1;
else
return 0;
}
/*算法2-4插入*/
int ListInsert(SqList *L,int pos,DataType item)
{
int i;
if(L->length>=LISTSIZE)
{
printf("顺序表已满,无法进行插入操作!");
return 0;
}
if(pos<=0 || pos>L->length+1)
{
printf("插入位置不合法,其取值范围应该是[1,length+1]");
return 0;
}
for(i=L->length-1; i>=pos-1; i--)
L->items[i+1]=L->items[i];
L->items[pos-1]=item;
L->length++;
return 1;
}
/*算法2-5删除*/
int ListDelete(SqList *L,int pos,DataType *item)
{
int i;
if(ListEmpty(*L))
{
printf("顺序表为空表,无法进行删除操作!");
return 0;
}
if(pos<1 || pos>L->length)
{
printf("删除位置不合法,其取值范围应该是[1,length]");
return 0;
}
*item=L->items[pos-1];
for(i=pos;i<L->length;i++)
L->items[i-1]=L->items[i];
L->length--;
return 1;
}
/*算法2-6查找指定元素在顺序表中的位置*/
int Find(SqList L,DataType item)
{
int pos=0;
if(ListEmpty(L))
{
printf("顺序表为空表,无法进行查找操作!");
return 0;
}
while(pos<L.length && L.items[pos]!=item)
pos++;
if(pos<L.length)
return pos+1;
else
return 0;
}
/*算法2-7获取顺序表中指定位置上的数据元素*/
int GetElem(SqList L,int pos,DataType *item)
{
if(ListEmpty(L))
return 0;
if(pos<=0 || pos>L.length)
{
printf("位置信息输入不合法,请重新输入");
return 0;
}
*item=L.items[pos-1];
return 1;
}
/*算法2-8遍历顺序表*/
int TraverseList(SqList L)
{
int i;
for(i=0;i<L.length;i++)
printf("%d\t",L.items[i]);
printf("\n");
return 1;
}
/*补充顺序表的建立算法*/
void CreateList(SqList *L,int n)/*顺序表的建立:*/ { int i;
for (i=0;i<n;i++)
scanf("%d",&L->items[i]);
L->length=n;
}
2、编写源程序实现对顺序表的插入删除等基本操作。
/* 顺序表的基本操作实现 */
#include "../sqlist.h"
int main(int argc, char* argv[])
{
SqList L;
int n=10; /*欲建立的顺序表长度*/
L.length=0;
CreateList(&L,n); /*建立顺序表*/
TraverseList(L); /*遍历顺序表*/
printf("%d",ListLength(L));/*打印顺序表长度*/
printf("\n");
}
(二)单链表的基本操作实现实验
1、建立头文件LinkList.h,完成单链表的类型定义及基本操作。
/*************************************/
/*单链表的头文件,文件名LinkList.h */
/*************************************/
#include "malloc.h"
#include "stdio.h"
/*单链表的存储结构*/
typedef int DataType;
#define NULL 0
typedef struct Node
DataType data;
struct Node *next;
}LNode,*PNode,*LinkList;
/*算法2-9初始化单链表*/
int InitList(LinkList *h)
{
*h=(LinkList)malloc(sizeof(LNode)); if(!h)
{
printf("初始化链表错误!\n");
return 0;
}
(*h)->next=NULL;
return 1;
}
/*算法2-10求单链表表长*/
int ListLength(LinkList h)
{
int total=0;
PNode p=h->next;
while(p)
{
total++;
p=p->next;
}
return total;
/*算法2-11判断单链表是否为空*/
int ListEmpty(LinkList h)
{
if(h->next)
return 0;
else
return 1;
}
/*算法2-12插入*/
int ListInsert(LinkList h,int pos,DataType x) {
PNode p=h,q;
int i=0;
while(p && i<pos-1)
{
p=p->next;
i++;
}
if(!p || i>pos-1)
{
printf("插入位置不合法!\n");
return 0;
}
q=(PNode)malloc(sizeof(LNode));
if(!q)
{
printf("不能生成新结点\n");
return 0;
}
q->data=x;
q->next=p->next;
p->next=q;
return 1;
}
/*算法2-13删除*/
int ListDelete(LinkList h,int pos,DataType *item) {
PNode p=h,q;
int i=0;
while(p->next && i<pos-1)
{
p=p->next;
i++;
}
if(!p->next || i>pos-1)
{
printf("删除位置不合法!\n");
return 0;
}
q=p->next;
p->next=q->next;
*item=q->data;
free(q);
return 1;
}
/*算法2-14查找指定元素在单链表中的位置*/ PNode Find(LinkList h,DataType item)
{
PNode p=h->next;
while(p && p->data!=item)
p=p->next;
return p;
}
/*算法2-15获取单链表中指定位置上的数据元素*/ int GetElem(LinkList h,int pos,DataType *item) {
int i=0;
PNode p=h->next;
while(p && i<pos-1)
{
i++;
p=p->next;
}
if(!p || i>pos-1)
{
printf("位置参数不合法!\n");
return 0;
}
*item=p->data;
return 1;
}
/*算法2-16销毁单链表*/
void DestroyList(LinkList h)
{
PNode p=h->next;
while(h)
{
p=h;
h=h->next;
free(p);
}
}
/*算法2-17遍历单链表*/
void TraverseList(LinkList h)
{
PNode p=h->next;
while(p)
{
printf("%d\t",p->data);
p=p->next;
}
printf("\n");
}
2、编写源程序实现对单链表的插入删除等基本操作。
/* 单链表的基本操作实现 */
#include "../LinkList.h"
int main(int argc, char* argv[])
{int i,x;
LinkList h;
h=(LinkList)malloc(sizeof(lnode));
/*由系统生成一个LNode型的结点,同时将该结点的起始位置赋给指针变量h */
creat(h);
TraverseList (h);
printf("请输入欲插入的元素:\n");
scanf("%d",&x);
printf("请输入欲插入元素的位置:\n");
scanf("%d",&i);
insert(h,i,x);
TraverseList (h);
printf("请输入欲删除的结点:\n");
scanf("%d",&x);
Delete(h,x);
TraverseList (h);
}
实验二栈和队列
一、实验目的
1.掌握栈和队列的顺序存储结构和链式存储结构,以便在实际背景下灵活
运用;
2.掌握栈和队列的特点,即后进先出与先进先出的原则;
3.掌握栈和队列的基本操作,如入栈与出栈、入队与出队等;
4.运用栈和队列解决问题。
二、实验内容和步骤
1.利用顺序栈将一个非负的十进制整数N转换为对应的B进制数。
将源程序以实验3—1为文件名保存在自己的文件夹里面。
2.利用链栈进行后缀表达式求值。
将源程序以实验3—2为文件名保存在自
己的文件夹里面。
选作:
3.实现汉诺塔问题算法,模拟圆盘移动过程。
4.实现迷宫问题算法,要求输出迷宫及其问题可解时的路径。
三、实验提示
(一)利用顺序栈将一个非负的十进制整数N转换为对应的B进制数。
1、建立头文件SqStack.h,完成顺序栈类型定义及基本操作
/* 顺序栈的头文件SqStack.h */
#include<stdio.h>
/*顺序栈存储结构*/
#define STACKSIZE 100
typedef int DataType;
typedef struct
{
DataType items[STACKSIZE];
int top;
}SqStack;
/*算法3-1初始化顺序栈*/
int InitStack(SqStack *S)
{
S->top=-1;
return 1;
}
/*算法3-2判空栈*/
int StackEmpty(SqStack S)
{
if(S.top==-1)
return 1;
else
return 0;
}
/*算法3-3入栈*/
int Push(SqStack *S,DataType e)
{
if(S->top>=STACKSIZE-1)
{
printf("堆栈已满,不能完成入栈操作!\n");
return 0;
}
S->top++;
S->items[S->top]=e;
return 1;
}
/*算法3-4出栈*/
int Pop(SqStack *S,DataType *e)
{
if(S->top<=-1)
{
printf("堆栈已空,不能完成出栈操作!\n");
return 0;
}
*e=S->items[S->top];
S->top--;
return 1;
}
/*算法3-5 取栈顶元素*/
int GetTop(SqStack S,DataType *e)
{
if(S.top<=-1)
{
printf("堆栈已空,不能完成取栈顶元素操作!\n");
return 0;
}
*e=S.items[S.top];
return 1;
}
2、编写源程序实现将一个非负的十进制整数N转换为对应的B进制数。
(二)利用链栈进行后缀表达式求值。
1、建立头文件LinkStack.h,完成链栈类型定义及基本操作
/* 链栈的头文件LinkStack.h */
#include "stdio.h"
#include "malloc.h"
/*链栈存储结构*/
typedef int DataType;
typedef struct SNode{
DataType data;
struct SNode* next;
}SNode, *LinkStack;
/*算法3-6初始化链栈*/
int InitStack(LinkStack *top)
{
*top=(LinkStack)malloc(sizeof(SNode)); if(*top==NULL)
{
printf("初始化链栈出错!\n");
return 0;
}
(*top)->next=NULL;
return 1;
}
/*算法3-7判空栈*/
int StackEmpty(LinkStack top)
{
if(top->next==NULL)
return 1;
else
return 0;
}
/*算法3-8入栈*/
int Push(LinkStack top,DataType e) {
SNode *p;
p=(SNode*)malloc(sizeof(SNode)); if(!p)
{
printf("入栈操作出错!\n");
return 0;
}
p->data=e;
p->next=top->next;
top->next=p;
return 1;
}
/*算法3-9出栈*/
int Pop(LinkStack top,DataType* e)
{
SNode *p;
if(!top->next)
{
printf("栈已空,无法完成出栈操作!\n");
return 0;
}
p=top->next;
top->next=p->next;
*e=p->data;
free(p);
return 1;
}
/*算法3-10 取栈顶元素*/
int GetTop(LinkStack top,DataType* e)
{
SNode *p;
if(!top->next)
{
printf("栈已空,无法完成取栈顶元素操作!\n");
return 0;
}
p=top->next;
*e=p->data;
return 1;
}
/*算法3-11销毁链栈*/
int Destroy(LinkStack top)
{
SNode *p;
while(top)
{
p=top;
top=top->next;
free(p);
}
return 1;
}
2、编写源程序实现插入删除等基本操作,完成后缀表达式求值算法。
实验三串的连接
一、实验目的
1.掌握串的顺序定长存储结构的类型定义方法
2.掌握串的堆分配存储结构的类型定义方法
3.理解串的基本模式匹配算法
二、实验内容和步骤
1.利用串的顺序定长存储结构实现两个子串的连接。
要求:两个子串从键盘输入获得;从屏幕显示连接后的新串元素列表。
将源程序以实验4-1为文件名保存在自己的文件夹里面。
选作:
2.利用串的堆配存储结构实现两个子串的连接。
3.上机实现朴素的串匹配算法。
要求:
从键盘输入主串和子串元素,调用朴素的串匹配算法,判断子串是否在主串
中,若在,返回起始位置,否则显示否定信息。
三、实验提示
(一)利用串的顺序定长存储结构实现两个子串的连接。
1、建立头文件SqString.h,完成顺序串类型定义及基本操作
/* 串的定长顺序存储头文件SqString.h */
#include<stdio.h>
/*存储结构*/
#define STRSIZE 100
typedef struct{
char ch[STRSIZE];
int length;
}SqString;
/*算法4-1初始化串*/
int InitString(SqString *S,char *str)
{
int i, len=0;
char *c=str;
while(*c!='\0'){len++;c++;} /*求str的长度*/
S->length = len; /*置串的当前长度值*/ for(i = 0; i < S->length; i++) /*赋值串值*/ S->ch[i] = str[i];
return 1;
}
/*算法4-2串插入*/
int StrInsert(SqString *S,int pos,SqString T)
{
int i;
if(pos<0 || pos>S->length)
{
printf("插入位置不合法,其取值范围应该是[0,length]");
return 0;
}
/*插入后串长≤STRSIZE,则正常插入*/
if (S->length + T.length<=STRSIZE)
{
for(i=S->length-1; i>=pos-1; i--)
S->ch[i+T.length]=S->ch[i];
for(i=0; i<T.length; i++)
S->ch[i+pos]=T.ch[i];
S->length+=T.length;
}
/*插入后串长>STRSIZE,则串T可以全部插入,串S部分被截断*/ else if(T.length+pos<=STRSIZE)
{
for (i=STRSIZE-1;i>T.length+pos-1;i--)
S->ch[i]=S->ch[i-T.length];
for (i=0;i<T.length;i++)
S->ch[i+pos]=T.ch[i];
S->length=STRSIZE;
}
/*插入后串长>STRSIZE,并且串T部分也要被截断*/
else
{
for (i=0;i<STRSIZE-pos;i++)
S->ch[i+pos]=T.ch[i];
S->length=STRSIZE;
}
return 1;
}
/*算法4-3串删除*/
int StrDelete(SqString *S,int pos,int len)
{
int i;
if(S->length<=0)
{
printf("空串,无法进行删除操作!");
return 0;
}
if(pos<0 || len<=0 || pos>S->length)
{
printf("删除位置pos以及删除长度len不合法,无法完成删除操作!");
return 0;
}
if(pos+len>S->length) len=S->length-pos+1; /*当删除长度超过串长度,则只删到串尾即可*/
for(i=pos+len;i<S->length;i++)
S->ch[i-len]=S->ch[i];
S->length-=len;
return 1;
}
/*算法4-4求子串*/
int SubStr(SqString S,int pos,int len,SqString *T)
{
int i;
if(S.length<=0)
{
printf("空串,无法完成求子串操作!");
return 0;
}
if(pos<0 || len<=0 || pos>S.length)
{
printf("子串的位置pos以及子串长度len不合法,无法完成求子串操作!");
return 0;
}
if(pos+len>S.length) len=S.length-pos+1; /*当子串长度超过主串长度,则只取到串尾即可*/
for(i=0;i<len;i++)
T->ch[i]=S.ch[i+pos];
T->length=len;
return 1;
}
/*算法4-5串连接*/
int Concat(SqString *S,SqString T)
{
int i;
if(S->length+T.length<=STRSIZE)/*连接后串长≤STRSIZE*/
{
for(i=0;i<T.length;i++)
S->ch[i+S->length]=T.ch[i];
S->length+=T.length;
}
else if(S->length<STRSIZE)/*连接后串长大于STRSIZE,但串S的长度小于STRSIZE,即连接后串T的部分字符序列被舍弃*/
{
for(i=S->length;i<STRSIZE;i++)
S->ch[i]=T.ch[i-S->length];
S->length=STRSIZE;
}
return 1;
}
/*算法4-6串比较*/
int StrCmp(SqString S, SqString T)
{
int i;
for (i=0;i<S.length && i<T.length;i++)
if (S.ch[i]!=T.ch[i])
return(S.ch[i] - T.ch[i]);
return(S.length - T.length);
}
/*算法2-7串定位
int GetElem(SqList L,int pos,DataType *item) {
if(ListEmpty(L))
return 0;
if(pos<=0 || pos>L.length)
{
printf("位置信息输入不合法,请重新输入");
return 0;
}
*item=L.ch[pos-1];
return 0;
}*/
/*算法2-8遍历顺序表
int TraverseList(SqList L)
{
int i;
for(i=0;i<L.length;i++)
printf("%d\t",L.ch[i]);
printf("\n");
return 1;
}*/
2、编写源程序实现插入删除等基本操作,完成两个子串的连接算法。
#include "../SqString.h"
int main(int argc, char* argv[])
{
int i;
//SqString S={"Strings",7};
//SqString T={" Demo",5};
SqString S,T,R;
InitString(&S,"Strings");
InitString(&T," Demo");
InitString(&R,"");
StrInsert(&S,7,T);
for(i=0;i<S.length;i++)
printf("%c",S.ch[i]);
printf("\n");
StrDelete(&S,6,5);
for(i=0;i<S.length;i++)
printf("%c",S.ch[i]);
printf("\n");
return 0;
}
实验四数组和广义表
一、实验目的
1.了解数组的两种存储表示方法,掌握数组在作为运行的存储结构中的地址计算方法;
2.了解稀疏矩阵的两种压缩方法的特点和适用范围,领会稀疏矩阵运算采用的处理方法。
3.理解广义表实现方法。
二、实验内容及步骤
1.用C语言编程实现稀疏矩阵的转置,将源程序以实验5-1为文件名保存在自己的文件夹里面。
①采用三元组顺序表创建一个稀疏矩阵;
②将矩阵的行列值相互交换;
③将每个三元组中的i和j相互调换;
④重排三元组之间的次序实现矩阵转置。
选作:
2、用C语言编程实现两稀疏矩阵的乘积
①采用行逻辑链接的顺序表建立两个稀疏矩阵;
②求两稀疏矩阵的乘积
3.实现广义表的递归算法,如求广义表的深度算法。
将源程序以实验5-2为文件名保存在自己的文件夹里面。
三、思考问题
结合实验过程,回答下列问题:
1、两稀疏矩阵相乘,其乘积是否一定为稀疏矩阵?
实验五二叉树及其应用
一、实验目的
1.掌握构造二叉链表树的算法。
2.掌握遍历二叉树的三种递归算法。
3.掌握计算二叉树深度、二叉树结点所在层次、二叉树叶子结点和二叉树所有路径的算法。
4.理解树的遍历算法和哈夫曼树的构造算法
二、实验内容及步骤
1.用C语言编程实现二叉树的中序遍历算法
①采用二叉链存储结构创建一个二叉树;
②用非递归方法实现二叉树的中序遍历算法,将源程序以实验6-1为文件名保存在自己的文件夹里面。
③输出二叉树中每个结点的值;
④给定具体数据调试程序。
2、用C语言编程实现在线索二叉树上进行遍历
①先进行二叉树的线索化,即建立线索二叉树;
②在线索二叉树中遍历每个结点并输出每个结点的信息;
③给定具体数据调试程序。
3.增加二叉树的基本操作,如计算二叉树深度、二叉树结点所在层次、二叉树叶子结点和二叉树所有路径等算法。
然后分别调用相应算法并显示对应结果。
将源程序以实验6-2为文件名保存在自己的文件夹里面。
三、思考问题
结合实验过程,回答下列问题:
1、采用非递归方法实现二叉树遍历与采用递归方法实现二叉树的遍历,哪个方法执行效率高;
2、为什么在线索二叉树上进行遍历,要比在二叉树上进行遍历快捷方便?
实验六哈夫曼编码
一、实验目的
1.掌握最优二叉树的含义。
2.掌握最优二叉树的结构特征,以及各种存储结构的特点及使用范围。
3.掌握哈夫曼编码的构成。
二、实验内容及步骤
1、假定用于通信的电文由8个字母A、B、C、D、E、F、G、H组成,各字母在电文中出现的概率为5%,25%,4%,7%,9%,12%,30%,8%,试编程为这8个字母设计赫夫曼编码。
①分析问题
②编程创建此问题的赫夫曼树;
③编程求出此8个字母赫夫曼编码并输出;将源程序以实验6-1为文件名保存在自己的文件夹里面。
④调试程序。
三、思考问题
结合实验过程,回答下列问题:
针对同一问题,构成的赫夫曼树是否是唯一的,构成的赫夫曼编码是否唯一?
实验七图的遍历及应用
一、实验目的
1、掌握图的基本存储方法;
2、掌握图的两种搜索路径的遍历算法;
3、掌握拓扑排序算法;(选做)
二、实验内容及步骤
1.建立ADT图的头文件及其相应操作。
调用图的遍历算法,显示遍历结果。
将源程序以实验7-1为文件名保存在自己的文件夹里面。
①采用邻接表存储结构创建一个图;
②编程实现图的深度优先搜索(或广度优先搜索)遍历算法
③输出遍历结果;
④给定具体数据调试程序。
2、教学计划编制问题
软件专业的学生要学习一系列课程,其中有些课程必须在其先修课程完成后才能学习,具体关系见下表:
假设每门课程的学习时间为一学期,试为该专业的学生设计教学计划,使他们能在最短的时间内修完这些课程。
分析问题;
①根据此问题创建一个图表示课程与课程之间的关系;
②利用拓扑排序算法实现该教学计划;
③输出课程开出的先后顺序
④调试程序。
三、思考问题
结合实验过程,回答下列问题:
1、图有哪几种存储结构,哪种适合于存储无向图,哪种适合于存储有向
图?;
2、列举出几种需要应用关键路径或最短路径算法解决的实际问题。
实验八查找及其应用
一、实验目的
1、掌握静态查找表算法(重点掌握折半查找);
2、掌握动态查找表----二叉排序树查找算法;
3、掌握哈希表查找算法
二、实验内容及步骤
1、用C语言编程实现有序表的折半查找算法
①创建一个递增的有序表;
②给定一个值,用折半查找算法在有序表中进行查找;
③输出查找结果;
④给定具体数据调试程序
2、用C语言编程实现在二叉排序树中进行查找
①读入一串整数,采用二叉链存储结构创建一棵二叉排序树;
②给定一个值,在二叉排序树中进行查找;
③输出查找结果;
④给定具体数据调试程序。
3、哈希表查找
针对某个集体(比如你所在的班级)中的“人名”设计一个哈希表,使得平均查找长度不超过R,完成相应的建表和查找程序。
①分析问题;
②创建此问题的哈希表;
③指定一个人名,在哈希表中进行查找,并输出查找结果;
④调试程序。
三、思考问题
结合实验过程,回答下列问题:
何种情况适合采用折半查找、何种情况适合采用二叉排序树查找、何种情况适合采用哈希表查找?
实验九内部排序
一、实验目的
1、掌握常用的排序方法(如:希尔排序、快速排序、选择排序、归并排序),
并掌握用高级语言实现排序算法;
2、深刻理解排序的定义和常用排序方法的特点,并能加以灵活应用;
3、了解常用方法的排序过程及其依据的原理。
二、实验内容及步骤
编程实现相关排序算法,将源程序以实验9-1为文件名保存在自己的文件夹里面。
1、用C语言编程实现插入排序算法
给出n个学生的考试成绩表,每条信息由姓名与分数组成,用一种插入排序算法编程实现:
①按分数高低次序输出每个学生在考试中获得的名次,分数相同的为
同一名次;
②按名次列出每个学生的姓名与分数。
2、用C语言编程实现快速排序算法
给出n个学生的考试成绩表,每条信息由姓名与分数组成,用一种快速排序算法编程实现:
①按分数高低次序输出每个学生在考试中获得的名次,分数相同的为
同一名次;
②按名次列出每个学生的姓名与分数。
3、用C语言编程实现选择排序算法
给出n个学生的考试成绩表,每条信息由姓名与分数组成,用一种选择排序算法编程实现:
①按分数高低次序输出每个学生在考试中获得的名次,分数相同的为
同一名次;
②按名次列出每个学生的姓名与分数。
4、用C语言编程实现归并排序算法
给出n个学生的考试成绩表,每条信息由姓名与分数组成,用归并排序算法编程实现:
①按分数高低次序输出每个学生在考试中获得的名次,分数相同的为
同一名次;
②按名次列出每个学生的姓名与分数。
三、思考问题
结合实验过程,回答下列问题:
何种情况适合采用插入排序算法处理排序问题、何种情况适合采用快速排序算法处理排序问题、何种情况适合采用选择排序算法处理排序问题、何种情况。