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、掌握树的前根序、中根序和后根序遍历算法
二、实验内容
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(pLchild);
}
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
程序示例:
//queue:
:
push(),queue:
:
pop(),queue:
:
empty(),queue:
:
back(),
//queue:
:
front(),queue:
:
size()
#include
#include
usingnamespacestd;
typedefqueueINTQUEUE;
typedefqueueCHARQUEUE;
intmain(void)
{
intsize_q;
INTQUEUEq;
CHARQUEUEp;
//Insertitemsinthequeue
q.push(42);
q.push(100);
q.push(49);
q.push(201);
//Outputthesizeofqueue
size_q=q.size();
cout<<"sizeofqis:
"<//Outputitemsinqueueusingfront()
//andusepop()togettonextitemuntil
//queueisempty
while(!
q.empty())
{
cout<q.pop();
}
//Insertitemsinthequeue
p.push("cat");
p.push("ape");
p.push("dog");
p.push("mouse");
p.push("horse");
//Outputtheiteminsertedlastusingback()
cout<
//Outputthesizeofqueue
size_q=p.size();
cout<<"sizeofpis:
"<//Outputitemsinqueueusingfront()
//andusepop()togettonextitemuntil
//queueisempty
while(!
p.empty())
{
cout<
p.pop();
}
}
输出结果:
sizeofqis:
4
42
100
49
201
horse
sizeofpis:
5
cat
ape
dog
mouse
horse
实验四二叉排序树
一、实验目的
掌握二叉排序树的构造
二、实验内容
(1)构建一个二叉排序树(中序遍历的时候会输出排序结果),树中结点数据取自数组a[10]。
a[10]={8,3,6,1,5,2,9,7,4,0}
(2)分别用三种遍历方法输出遍历结果。
(3)键盘输入一个值x,要求在生成好的二叉排序树中查找这个值x,如果找到,则输出“找到了”,没有找到,则输出“没有找到”
实验五排序
一、实验目的
掌握快速排序
二、实验要求
复习排序方法,掌握快速排序算法,并自己编写代码实现
三、实验内容
1、快速排序
编写程序,实现快速排序。
从键盘上输入10个整数,存放在数组中,然后用快速排序法对其从小到大进行排序,并输出排序结果。
2、选作
编写程序,实现堆排序。
实验六最短路径
一、实验目的
1.学习掌握图的存储结构
2.学会编写求最短路径的算法
二、实验内容
1、实验题目
编写代码实现Dijkstra生成最短路径的算法,其中要有完整的图的输入输出
2、简单介绍
图的存储:
用邻接矩阵,这样会方便不少。
邻接矩阵是一个二维数组,数组中的元素是边的权(一些数值),数组下标号为结点的标号。
(1)例如二维数组中的一个元素M[5][6]的值为39,则表示结点5、6连接,且其上的权值为39。
(2)用邻接矩阵存储图,对图的读写就简单了。
因为邻接矩阵就是一个二维数组,因此对图的读写就是对二维数组的操作。
只要能弄清楚边的编号,就能把图读入了。
用一对结点表示边(也就是输入的时候输入一对结点的编号)
求最短路径的算法:
求最短路径就是求图中的每一个点到图中某一个给定点(这里认为是编号为0的点)的最短距离。
具体算法就是初始有一个旧图,一个新图。
开始的时候旧图中有所有的结点,新图中初始为只有一个结点(源点,路径的源头)。
整个算法就是不停的从旧图中往新图中添加点,直到所有的点都添加到新图中为止。
要实现这个算法,除了用二维数组保存图,还需要使用到两个辅助的数组
数组find[N]:
此数组是用来表示标号对应的结点是否已经被添加到新图中(因为只有旧图中的点我们才需要添加到新图中,并且只有旧图中点到源点的距离,我们才需要进行更新)其中N为图中结点的个数。
数组distance[N]:
此数组记录图中的点到源点的距离。
这个数组里面存放的值是不断进行更新的。
其中N为图中结点的个数。
3、程序简单模板
只是参考,不需要照着这个来写
//最短路径
#ifndefMYGRAPH_H_
#defineMYGRAPH_H_
classMyGraph
{
public:
voidreadUndirectedGraph();
MyGraph(intsize);//构造函数中设置图的大小,分配空间
voidwriteGraph();
voidshortPath(intsource);//求最短路径
protected:
private:
int**m_graph;//用二维数组保存图
intm_size;//图的大小
};
#endif
/////////////////////////////////////////////////////////////////////
//构造函数中设置图的大小,分配空间
MyGraph:
:
MyGraph(intsize)
{
inti,j;
m_size=size;
//给图分配空间
m_graph=newint*[m_size];
for(i=0;i{
m_graph[i]=newint[m_size];
}
for(i=0;i{
for(j=0;j{
m_graph[i][j]=INT_MAX;
}
}
}