数据结构实验指导书.docx

上传人:b****4 文档编号:12340991 上传时间:2023-04-18 格式:DOCX 页数:30 大小:62.21KB
下载 相关 举报
数据结构实验指导书.docx_第1页
第1页 / 共30页
数据结构实验指导书.docx_第2页
第2页 / 共30页
数据结构实验指导书.docx_第3页
第3页 / 共30页
数据结构实验指导书.docx_第4页
第4页 / 共30页
数据结构实验指导书.docx_第5页
第5页 / 共30页
点击查看更多>>
下载资源
资源描述

数据结构实验指导书.docx

《数据结构实验指导书.docx》由会员分享,可在线阅读,更多相关《数据结构实验指导书.docx(30页珍藏版)》请在冰豆网上搜索。

数据结构实验指导书.docx

数据结构实验指导书

给大家的实验文档中分为一下几部分

1.实验准备:

请好好复习C语言,有时间也复习一下C++。

2.c语言实验教案中是一些c语言的基础知识,包括VC环境的使用和程序的调试,希望对c语言已经忘记的同学好好看看复习一下。

(程序的编写调试是长年累月的过程,需要不断的积累,写得多了,程序调试的多了,自然就熟练了)

3.对应的flash课件:

其中是一些实验的flash课件演示,给大家做一下参考

4.实验指导书和实验教案大家在做每个实验前都需要看看。

阅读的时候,可以使用【视图】|【文档结构图】,可以比较自由跳到相应位置

5.总体实验难度比较大,时间紧,单靠实验课上的几个学时,作为初学者是无法完成的,需要大家在课前课后尽自己最大的努力。

6.每个实验的代码编写可以用c也可以用c++

7.实验前要写预习报告,格式跟实验报告一致,实验结束后,可以直接在其上修改实验代码,加上实验小结,作为实验报告上交。

实验报告必须手写!

代码部分可以只写关键代码。

实验安排

1、多项式加减法,2学时

2、栈和队列的应用,2学时

3、迷宫,4学时

4、二叉树的建立和遍历,4学时

5、归并排序,2学时

6、图,2学时

实验一多项式加减法

一、实验目的

通过实现多项式的加减法,对链表有更深入的了解

二、实验内容

问题描述:

设计一个一元稀疏多项式简单的加减法计算器

实现要求:

一元稀疏多项式简单计算器的基本功能是:

(1)输入并建立多项式:

(2)输出多项式

(3)多项式A和B相加,建立多项式C=A+B,并输出相加的结果多项式C

(4)选作:

多项式A和B相减,建立多项式C=A-B,并输出相加的结果多项式D

方法说明:

(1)多项式的输入与存储

用带表头结点的单链表存储多项式,链表中的每个节点分别存储多项式各项的系数和指数,即每从键盘输入多项式的一对数(系数,指数),可对应建立链表的一个结点。

每个节点的结构为:

建立两个链表,其中pa和pb分别为它们的头指针:

Pa

pb

结果链表

Pa(或者是Pc)

Pc

(2)多项式数据类型的定义

structtagNode

{

floatcoef;

intexp;

structtagNode*next;

};

typedefstructtagNodeNode;

typedefstructtagNode*pNode;

(3)主要算法

①创建两个链表,分别存放多项式1和多项式2,这两个链表中的节点是按指数降序或者升序排列的

②多项式相加或相减,下面给出多项式相加的部分实现

/*

下面的函数实现两个多项式的相加,要相加的链表分别由pa和pb指向(其中,pa,pb都是分配了空间的头结点)。

相加的结果直接由pa指向的链表保存,即是在pa链表中添加或删除(当系数因为相加为0的情况下)一些结点,构成结果。

这里要相加的链表中指数都是按从小到大的顺序排列好了的,是升序链表。

*/

voidadd_poly(Node*pa,Node*pb)

{

Node*p=pa->pNext;//链表1,将来的结果也放在此

Node*q=pb->pNext;//链表2

Node*pre=pa;

Node*u;//临时用

floatx;

while(p!

=NULL&&q!

=NULL)//当两个链表都不为空

{

if(p->expexp)//比较链表1跟链表2当前节点的指数大小,链表1也是存放结果的地方

{

pre=p;

p=p->pNext;//p指向要比较的下一个结点。

pre指向的是结果链表的最后一个结点。

}

elseif(p->exp==q->exp)//假如链表1和链表2的指数相等,就要系数相加

{

x=p->coef+q->coef;

if(x!

=0)//相加后的系数不为0,有必要保留一个结点就可以了

{

p->coef=x;

pre=p;

}

else//如果相加后,系数不是0,不需要保留任何一个结点,在这里删除链表1的结点,下面删除链表2的结点

{

pre->pNext=p->pNext;//保持链表1的连续性

free(p);

}

p=pre->pNext;//p指向要比较的下一个结点

//下面的代码是进行链表2结点的删除工作,因为指数相等,仅仅需要保留一个结点就可以了

//而结果直接保存在链表1中,所以,删除链表2的结点。

u=q;

q=q->pNext;

free(u);

}

else//如果链表2的当前节点指数小,那么要把链表2的当前节点加入到结果链表中(即是链表1)

{//相当于把结点插入到链表1中,用u作为临时变量,保存链表2的下一个当前节点的位置。

u=q->pNext;

q->pNext=p;

pre->pNext=q;

pre=q;

q=u;

}

}

if(q)//如果链表2比链表1长,那么需要把链表2多余的部分加入结果链表中。

链表1比链表2长,则什么都不用做。

{

pre->pNext=q;

}

free(pb);

}

③输出结果多项式

实验二栈和队列的应用

一、实验目的

1、掌握栈的编写和应用

2、掌握队列的编写和应用

二、实验内容

1、分别使用STL中的栈和自己编写的栈类,实现序列的反转

(1)简单修改下面代码,实现使用STL中的栈进行序列的反转,编译运行

#include

intmain()

/*Pre:

Theusersuppliesanintegernandndecimalnumbers.

Post:

Thenumbersareprintedinreverseorder.

Uses:

TheSTLclassstackanditsmethods*/

{

intn;

doubleitem;

stacknumbers;//declaresandinitializesastackofnumbers

cout<<"Typeinanintegernfollowedbyndecimalnumbers."

<

<<"Thenumberswillbeprintedinreverseorder."

<

cin>>n;

for(inti=0;i

cin>>item;

numbers.push(item);

}

cout<

while(!

numbers.empty()){

cout<

numbers.pop();

}

cout<

}

提示:

(1)由于程序是用了STL(标准模板库,可以简单的看成是一个函数库,在其中有各种有用的类、函数和算法),栈在其中有实现。

栈在STL中的实现用到了类模板,也就是说其栈是独立于类型的,模板提供参数化类型,也就是能将类型名作为参数传递给接收方来建立类或函数。

比如stacknumbers;中就是声明了一个栈,这个栈中存放的数据类型为double。

(2)要使用c++的输入输出需要加上几行语句如下,因为cout和cin是在命名空间std中的:

#include

usingnamespacestd;

(2)自己编写程序实现栈

该栈可以用链表实现,也可以用数组实现。

C语言或者c++描述都可以。

该实现的栈要求至少具有

(1)压栈

(2)出栈(3)判断栈是否空(4)取栈顶元素值等功能。

如果用数组实现该栈,则该栈还需要具有下面函数(5)判断栈是否满

(3)使用自己编写的栈,进行序列的反转

2、自己编写程序,实现队列,并自己编写主程序测试该队列(选作)

该队列可以使用链表实现,也可以使用数组实现,C语言或者c++描述都可以。

实现队列后,再编写一个简单的主函数,测试自己编写的队列的各个功能。

要求:

自己实现的队列至少需要有如下功能:

(1)进队

(2)出队(3)取队首元素(4)判断队列是否为空。

如果是用数组实现的队列,至少还需要具有下面的函数(5)判断队列是否满

附录:

STL中栈的使用

#pragmawarning(disable:

4786)

#include

#include

usingnamespacestd;

typedefstackSTACK_INT;

intmain()

{

STACK_INTstack1;

cout<<"stack1.empty()returned"<<

(stack1.empty()?

"true":

"false")<

cout<<"stack1.push

(2)"<

stack1.push

(2);

if(!

stack1.empty())//Function3

cout<<"stack1.top()returned"<<

stack1.top()<

cout<<"stack1.push(5)"<

stack1.push(5);

if(!

stack1.empty())//Function3

cout<<"stack1.top()returned"<<

stack1.top()<

cout<<"stack1.push(11)"<

stack1.push(11);

if(!

stack1.empty())//Function3

cout<<"stack1.top()returned"<<

stack1.top()<

//Modifythetopitem.Setitto6.

if(!

stack1.empty()){//Function3

cout<<"stack1.top()=6;"<

stack1.top()=6;//Function1

}

//Repeatuntilstackisempty

while(!

stack1.empty()){//Function3

constint&t=stack1.top();//Function2

cout<<"stack1.top()returned"<

cout<<"stack1.pop()"<

stack1.pop();

}

}

运行结果:

stack1.empty()returnedtrue

stack1.push

(2)

stack1.top()returned2

stack1.push(5)

stack1.top()returned5

stack1.push(11)

stack1.top()returned11

stack1.top()=6;

stack1.top()returned6

stack1.pop()

stack1.top()returned5

stack1.pop()

stack1.top()returned2

stack1.pop()

实验三迷宫

一、实验目的

1、了解回溯法在求解迷宫问题中的应用

2、进一步掌握栈的使用

二、实验内容

用回溯法求解迷宫问题,可以用一个栈保存探索的序列。

并且在该迷宫的行走中,站在一点可以有八个方向选择。

比如如下的迷宫

Enter->0111000000

0001000100

0101100100

0100101100

0100101100

1110101000

0010001011

0010001011

0110101000

0000101100-->EXIT

下面是可能的路径(注意:

从入口到出口可能有多条路径,优先选择的方向不同,路径可能也不一样!

Path:

(maze[0][0],maze[1][0],maze[1][1],maze[1][2],maze[2][2],

maze[3][2],maze[3][3],maze[4][3],maze[5][3],maze[6][3],

maze[6][4],maze[6][5],maze[5][5],maze[4][5],maze[3][5],

maze[2][5],maze[2][6],maze[1][6],maze[0][6],maze[0][7],

maze[0][8],maze[1][8],maze[2][8],maze[3][8],maze[4][8],

maze[5][8],maze[5][7],maze[6][7],maze[7][7],maze[8][7],

maze[8][8],maze[8][9],maze[9][9])

Enter->X11100X---X---X0

X---X---X100X1X0

01X11X---X1X0

01X---X1X11X0

010X1X11X0

111X1X1X---X0

001X---X---X1X11

0010001X11

0110101X--X--X

000010110X-->EXIT

1、提示:

(1)数据结构:

✧用二维数组MAZE[m+2][n+2]表示迷宫的结构,数组中的值为1表示是墙,为0表示可以走通。

(用MAZE[m+2][n+2]而不用MAZE[m][n]的原因在于想表示和编写代码的时候简单些,而且让迷宫周围都是墙,防止错误的走出去)

✧用二维数组MARK[m+2][n+2]表示迷宫是否被走过,主要是为了回溯时已经证明走不通的路线就不要再去走了。

(用MARK[m+2][n+2]而不用MARK[m][n]的原因在于想表示和编写代码的时候简单些)

✧二维数据MOVE[8][2]是为了更方便的移动到下一步,改变坐标。

这个二维数组是为了更好的转换坐标(八个方向,从0到7),而且也能避免重复走路

✧用栈保存走过的路径

(2)输出:

✧迷宫布局,用0表示可以走通的地方,用1表示墙

✧如果能走通,则输出路径和路径的长度;若不能走通,则输出提示不能走通

✧带有路径的迷宫布局

2、伪代码

注意:

下面的仅仅是伪代码!

不能直接做代码使用的,揭示的仅仅是算法本身

Path(MAZE,MARK,m,n,MOVE,STACK)

//AbinarymatrixMAZE(0:

m+1,0:

n+1)holdsthemaze.

//STACK(mn,2)recordsthepath

{

MARK(1,1)=1;

STACK.push((1,1,1));

WhilenotSTACK.empty()

{

(i,j,mov)=STACK.top();

STACK.pop();

Whilemov!

=8

{

g=i+MOVE(mov,1);

h=j+MOVE(mov,2);

ifg=mandh=n

{

reverseprintSTACK;

printi,j;

printm,n;

return;

}

ifMAZE(g,h)=0andMARK(g,h)=0

{

MARK(g,h)=1;

STACK.push((i,j,mov));

i=g;

j=h;

mov=0;

}

elsemov=mov+1;

}

}

print“Nopathhasbeenfound”

}

实验四二叉树的建立和遍历

一、实验目的

1、设计数据结构和算法,实现按层次构造二叉树的算法

2、掌握树的前根序、中根序和后根序遍历算法

二、实验内容

1、实验题目

按层次(从上到下,从左到右的顺序)输入树的结点,如果该结点为空,则用一个特定的值替代(比如0或者.)。

例如下面的图中,输入为ebfad.g..c(当然为了方便输入,也可以用#结束字符串的输入)

要求构造一棵如下的二叉树,当二叉树构造成功后,需要对其进行先序遍历,后序遍历,中序遍历。

2、按层次构造树的两种方法

对于如下的一棵树

输入:

为了构造上图所示的这样一棵二叉树,键盘上输入的顺序如下:

ebfad.g..c#

其中可以看到这是根据层次的一种输入,先输入第一层的结点,然后是第二层的结点,第三层….直到把所有的带信息的结点输入完。

也可以看到,在输入的序列中,有.号,这是代表结点为空。

注意在输入的时候,为空的结点也要这样输入进去。

构造二叉树:

方法一:

用队列

queueA;

queueB;

假如我们把读入的数据放到一个队列中A,用于方便我们的后续处理,那么,在读入后,这个队列中的数据为ebfad.g..c,其中e为队列头存放的元素值(即该指针所指向的节点空间数据域中的值为e),而点代表空指针NULL

把数据读入队列A中的方法如下:

Binary_node*tempNode=newBinary_node();

cin>>tempNode->data;

tempNode->left=NULL;

tempNode->right=NULL;

A.push(tempNode);

为了按层次的构造二叉树,我们还要使用一个队列B,这个队列中保存的是指向要有儿子结点的父亲结点的指针。

下面是这两个队列的变化和树的构造变化情况:

(1)第一步很特殊,首先是树根

Binary_node*pNode=A.front();

A.pop();

B.push(pNode);

A:

bfad.g..c

B:

e

树:

(2)后面的每一步都是从A中取出两个队首,放入B队列尾部(如果为NULL则不放)。

从B中取出队首,队列A中取出的元素正好是B中取出元素的小孩子

Binary_node*pfather=B.front();

B.pop();

Binary_node*pLchild=A.front();//先出来的是左孩子

A.pop();

Binary_node*pRchild=A.front();

A.pop();

pfather->left=pLchild;

pfather->right=pRchild;

//先放入左孩子

if(pLchild!

=NULL)

{

B.push(pLchild);

}

if(pRchild!

=NULL)

{

B.push(pRchild);

}

A:

ad.g..c

B:

bf

树:

(3)

A:

.g..c

B:

fad

树:

(4)

A:

..c

B:

adg

树:

(5)

A:

c

B:

dg

树:

(6)

A:

空(当队列A为空的时候整个算法结束,树构造成功)

B:

g

树:

第二种方法:

给树的结点按层次从上到下,从左到右编号(编号从1开始,空节点也要编号),利用父亲跟小孩的编号的关系来编写代码。

即节点的编号除以2,得到的商代表这该节点父亲节点的编号,得到的余数为0,则表示该节点为父亲的左孩子,若得到的余数为1,则表示该节点为父亲的右孩子。

实现方法可以为,

(1)为每个节点分配空间;

(2)定义一个一维数组,该数组中存放的元素为指向节点的指针,将每个分配好空间的节点的指针放入该一维数组中(3)逐一访问节点,确定节点的父子关系。

当除了根节点外,每个节点的父亲都确定后,这颗二叉树就构造好了。

两种方法分析:

用队列的方法,实现有点难度,但是灵活。

数组的方法,实现比较简单,但是有局限性。

3、程序简单模板

#include

usingnamespacestd;

structBinary_node

{

chardata;//datamembers

Binary_node*left;

Binary_node*right;

};

classBinary_tree

{

public:

Binary_tree();//构造函数,里面将root=NULL;

//通过队列中保存的数据,构造树

voidbuildTree(void);

//遍历二叉树

voidpreorder(void);

voidinorder(void);

voidpostorder(void);

private:

//遍历树的辅助函数

voidrecursive_inorder(Binary_node*root);

voidrecursive_preorder(Binary_node*root);

voidrecursive_postorder(Binary_node*root);

Binary_node*root;//树根

};

这里给出一个C++的类,仅供参考,自己写代码的时候并不要求一定如此。

附录:

STL中队列的使用

注:

队列,这里也不要求大家再去自己实现一个有关队列的类,直接用标准模板库(STL)中的队列就可以了。

需要#include

STL中的queue,里面的一些成员函数如下(这里仅仅描述也许会用到的几个,具体不明白可以查找msdn,搜索queueclass):

front:

Returnsareferencetothefirstelementatthefrontofthequeue.

pop:

Removesanelementfromthefrontofthequeue

push:

Addsanelementtothebackofthequeue

empty:

Testsifthequeueisempty

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 商务科技

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

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