北京邮电大学数据结构实验报告与源代码实验三二叉树

合集下载

实验三 二叉树

实验三  二叉树

实验三二叉树
一、实验目的
1.掌握二叉树的链式存储结构及其相关操作的实现。

2.掌握二叉树的先序、中序、后序的递归遍历算法。

3.理解二叉树的各种非递归遍历算法的实现。

二、实验要求
1.实验前做好充分准备,包括复习第六章所学内容,事先预习好本次实验内容。

2.实验时记录实验结果,按要求完成各题。

3.实验结束后,给出实验总结与分析并及时给出本次实验的实验报告。

三、实验题目
本次实验给出的选定题目如下表所示。

说明:
(1)实验内容1)为必做内容。

(2)实验内容2)与实验内容3)为选做内容。

四、实验内容与要求
1、实验题目一:(1)二叉树的创建、递归遍历及其它基本操作的实现。

要求:定义用二叉链表表示的二叉树,并实现二叉树的创建、遍历(先序、中序后序)的递归算法及求深度操作等,并对其进行验证。

2、实验题目二:二叉树非递归遍历算法的实现
要求:在题目一的基础上,实现二叉树的非递归遍历算法(先序、中序、后序或按层),并对其进行验证。

3、实验题目三:哈夫曼树及哈夫曼编码的算法实现
要求:编程实现哈夫曼树的创建及利用哈夫曼树求解哈夫曼编码。

北邮数据结构实验报告

北邮数据结构实验报告

北邮数据结构实验报告北京邮电大学信息与通信工程学院2009级数据结构实验报告实验名称:实验三哈夫曼编/解码器的实现学生姓名:陈聪捷日期:2010年11月28日1.实验要求一、实验目的:了解哈夫曼树的思想和相关概念;二、实验内容:利用二叉树结构实现哈夫曼编/解码器1.初始化:能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立哈夫曼树。

2.建立编码表:利用已经建好的哈夫曼树进行编码,并将每个字符的编码输出。

3.编码:根据编码表对输入的字符串进行编码,并将编码后的字符串输出。

4.译码:利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出译码结果。

5.打印:以直观的方式打印哈夫曼树。

6.计算输入的字符串编码前和编码后的长度,并进行分析,讨论哈夫曼编码的压缩效果。

7.用户界面可以设计成“菜单”方式,能进行交互,根据输入的字符串中每个字符出现的次数统计频度,对没有出现的字符一律不用编码。

2.程序分析2.1存储结构二叉树templateclassBiTree{public:BiTree();//构造函数,其前序序列由键盘输入~BiTree(void);//析构函数BiNode*Getroot();//获得指向根结点的指针protected:BiNode*root;//指向根结点的头指针};//声明类BiTree及定义结构BiNodeData:二叉树是由一个根结点和两棵互不相交的左右子树构成data:HCode*HCodeTable;//编码表inttSize;//编码表中的总字符数二叉树的节点结构templatestructBiNode//二叉树的结点结构{Tdata;//记录数据Tlchild;//左孩子Trchild;//右孩子Tparent;//双亲};编码表的节点结构structHCode{chardata;//编码表中的字符charcode[100];//该字符对应的编码};待编码字符串由键盘输入,输入时用链表存储,链表节点为structNode{charcharacter;//输入的字符unsignedintcount;//该字符的权值boolused;//建立树的时候该字符是否使用过Node*next;//保存下一个节点的地址};示意图:2.2关键算法分析1.初始化函数(voidHuffmanTree::Init(stringInput))算法伪代码:1.初始化链表的头结点2.获得输入字符串的第一个字符,并将其插入到链表尾部,n=1(n 记录的是链表中字符的个数)3.从字符串第2个字符开始,逐个取出字符串中的字符3.1将当前取出的字符与链表中已经存在的字符逐个比较,如果当前取出的字符与链表中已经存在的某个字符相同,则链表中该字符的权值加1。

北邮数据结构平衡二叉树报告概论

北邮数据结构平衡二叉树报告概论

数据结构实验报告实验名称:平衡二叉树1.实验目的和内容根据平衡二叉树的抽象数据类型的定义,使用二叉链表实现一个平衡二叉树。

二叉树的基本功能:1、平衡二叉树的建立2、平衡二叉树的查找3、平衡二叉树的插入4、平衡二叉树的删除5、平衡二叉树的销毁6、其他:自定义操作编写测试main()函数测试平衡二叉树的正确性。

2. 程序分析2.1 存储结构struct node{int key; //值int height; //这个结点的父节点在这枝最长路径上的结点个数node *left; //左孩子指针node *right; //右孩子指针node(int k){ key = k; left = right = 0; height = 1; } //构造函数};2.2 程序流程2.3 关键算法分析(由于函数过多,在此只挑选部分重要函数)算法1:void AVL_Tree::left_rotate(node *&x)[1] 算法功能:对 R-R型进行调整[2] 算法基本思想:将结点右孩子进行逆时针旋转[3] 算法空间、时间复杂度分析:都为0(1)[4] 代码逻辑node *y = x->right; y为x的右孩子x->right = y->left; 将y的左孩子赋给x的右孩子 y->left = x; x变为y的左孩子fixheight(x); 修正x,y的height值fixheight(y);x = y; 使x的父节点指向y 算法2:void A VL_Tree::right_rotate(node *&x)[1] 算法功能:对L-L型进行调整[2] 算法基本思想:将左孩子进行顺时针旋转[3] 算法空间、时间复杂度分析:都为0(1)[4] 代码逻辑node *y = x->left; //y为x的左孩子 x->left = y->right; y的右孩子赋给x的左孩子y->right = x; x变为y的右孩子fixheight(x); 修正x和y的height值fixheight(y);x = y; 使x的父节点指向y算法3:node*& A VL_Tree::balance(node *&p)[1] 算法功能:对给定结点进行平衡操作[2] 算法基本思想:通过平衡因子判断属于哪种情况,再依照情况进行平衡[3] 算法空间、时间复杂度分析:没有递归和循环,都为O(1)[4] 代码逻辑fixheight(p); //修正P的height值if (bfactor(p) == 2) 平衡因子为2,为L-?型if (bfactor(p->left) < 0) P的左孩子平衡因子<0时,为L-R型,执行left_rotate(p->left); 相关平衡操作,若>0,为L-L型。

北邮数据结构实验报告

北邮数据结构实验报告

北邮数据结构实验报告摘要:本报告基于北邮数据结构实验,通过实际操作和实验结果的分析,总结和讨论了各实验的目的、实验过程、实验结果以及相关的问题和解决方法。

本报告旨在帮助读者了解数据结构实验的基本原理和应用,并为今后的学习和研究提供参考。

1. 实验一:线性表的操作1.1 实验目的本实验旨在掌握线性表的基本操作以及对应的算法实现,包括插入、删除、查找、修改等。

1.2 实验过程我们使用C++语言编写了线性表的相关算法,并在实际编程环境下进行了测试。

通过插入元素、删除元素、查找元素和修改元素的操作,验证了算法的正确性和效率。

1.3 实验结果经过测试,我们发现线性表的插入和删除操作的时间复杂度为O(n),查找操作的时间复杂度为O(n),修改操作的时间复杂度为O(1)。

这些结果与预期相符,并反映了线性表的基本特性。

1.4 问题与解决方法在实验过程中,我们遇到了一些问题,例如插入操作的边界条件判断、删除操作时的内存释放等。

通过仔细分析问题,我们优化了算法的实现,并解决了这些问题。

2. 实验二:栈和队列的应用2.1 实验目的本实验旨在掌握栈和队列的基本原理、操作和应用,并进行实际编程实现。

2.2 实验过程我们使用C++语言编写了栈和队列的相关算法,并在实际编程环境下进行了测试。

通过栈的应用实现表达式求值和逆波兰表达式的计算,以及队列的应用实现图的广度优先遍历,验证了算法的正确性和效率。

2.3 实验结果经过测试,我们发现栈的应用可以实现表达式的求值和逆波兰表达式的计算,队列的应用可以实现图的广度优先遍历。

这些结果证明了栈和队列在实际应用中的重要性和有效性。

2.4 问题与解决方法在实验过程中,我们遇到了一些问题,例如中缀表达式转后缀表达式的算法设计、表达式求值的优化等。

通过查阅资料和与同学的讨论,我们解决了这些问题,并完善了算法的实现。

3. 实验三:串的模式匹配3.1 实验目的本实验旨在掌握串的基本操作和模式匹配算法,并进行实际编程实现。

北邮数据结构第三次实验-实验报告

北邮数据结构第三次实验-实验报告

数据结构实验报告实验名称:实验三——栈和队列学生姓名:班级:班内序号:学号:日期:1.实验要求1.1 实验目的通过选择下面两个题目之一进行实现,掌握如下内容:➢掌握二叉树基本操作的实现方法➢了解赫夫曼树的思想和相关概念➢学习使用二叉树解决实际问题的能力1.2 实验内容根据二叉树的抽象数据类型的定义,使用二叉链表实现一个二叉树。

二叉树的基本功能:1、二叉树的建立2、前序遍历二叉树3、中序遍历二叉树4、后序遍历二叉树5、按层序遍历二叉树6、求二叉树的深度7、求指定结点到根的路径8、二叉树的销毁9、其他:自定义操作编写测试main()函数测试线性表的正确性2. 程序分析2.1 二叉链表2.2 二叉树的二叉链表存储示意图2.3 关键算法分析2.3.1算法1:void create(Binode<T> *&R, T data[], int i);[1] 算法功能:创建一个二叉树[2] 算法基本思想:通过构造函数创建一个二叉树,构造函数通过调用函数create()创建二叉树,关于函数create()的伪代码:1.定义根指针,输入节点储存的data,若输入“#”,则该节点为空;2.申请一个新节点,判断它的父结点是否不为空,如果不为空在判断其为左或者右孩子,并把地址付给父结点,把data写入。

[3] 算法空间、时间复杂度:O(n)[4] 代码逻辑(可用伪代码描述):if(data[i-1]!=0){R = new Binode<T>;R->data= data[i-1];R->lch = R->rch = NULL;create(R->lch, data,2*i);create(R->rch, data, 2*i+1);}2.3.2算法2:void Destroy(Binode<T> *R);[1] 算法功能:二叉树的销毁[2] 算法基本思想:采用后序遍历的方法,释放节点。

数据结构实验报告二叉树

数据结构实验报告二叉树
return s;
}
void dispbtnode1(btnode *b)
{
btnode *st[maxsize],*p;
int level[maxsize][2],top=-1,n,i,width=4;
char type;
if(b!=NULL)
{
top++;
st[top]=b;
level[top][0]=width;
level[top][0]=n+width;
level[top][1]=1;
}
if(p->lchild!=NULL)
{
top++;
st[top]=p->lchild;
level[top][0]=n+width;
level[top][1]=0;
}
}
}
}
2)先序,中序、后序遍历功能实现,因为想自己更能读懂理解程序,没有使用递归算法。
}
btnode *rchildnode(btnode *p)
{
return p->rchild ;
}
btnode * revers(btnode *b)//交换左右子树
{
if(b!=NULL)
{
if(b->rchild !=NULL||b->lchild !=NULL)
{
btn;lchild );
(3)根据二叉树的基本运算,设计先序遍历和中序遍历(或者中序遍历和后序遍历),确定二叉树的算法。
(4)在不改变原有二叉树结构的条件下,将二叉树左右孩子进行交换,并采用凹入表示法和括号表示法输出原有二叉树及交换子树后的二叉树。

数据结构实验三——二叉树基本操作及运算实验报告

数据结构实验三——二叉树基本操作及运算实验报告

《数据结构与数据库》实验报告实验题目二叉树的基本操作及运算一、需要分析问题描述:实现二叉树(包括二叉排序树)的建立,并实现先序、中序、后序和按层次遍历,计算叶子结点数、树的深度、树的宽度,求树的非空子孙结点个数、度为2的结点数目、度为2的结点数目,以及二叉树常用运算。

问题分析:二叉树树型结构是一类重要的非线性数据结构,对它的熟练掌握是学习数据结构的基本要求。

由于二叉树的定义本身就是一种递归定义,所以二叉树的一些基本操作也可采用递归调用的方法。

处理本问题,我觉得应该:1、建立二叉树;2、通过递归方法来遍历(先序、中序和后序)二叉树;3、通过队列应用来实现对二叉树的层次遍历;4、借用递归方法对二叉树进行一些基本操作,如:求叶子数、树的深度宽度等;5、运用广义表对二叉树进行广义表形式的打印。

算法规定:输入形式:为了方便操作,规定二叉树的元素类型都为字符型,允许各种字符类型的输入,没有元素的结点以空格输入表示,并且本实验是以先序顺序输入的。

输出形式:通过先序、中序和后序遍历的方法对树的各字符型元素进行遍历打印,再以广义表形式进行打印。

对二叉树的一些运算结果以整型输出。

程序功能:实现对二叉树的先序、中序和后序遍历,层次遍历。

计算叶子结点数、树的深度、树的宽度,求树的非空子孙结点个数、度为2的结点数目、度为2的结点数目。

对二叉树的某个元素进行查找,对二叉树的某个结点进行删除。

测试数据:输入一:ABC□□DE□G□□F□□□(以□表示空格),查找5,删除E预测结果:先序遍历ABCDEGF中序遍历CBEGDFA后序遍历CGEFDBA层次遍历ABCDEFG广义表打印A(B(C,D(E(,G),F)))叶子数3 深度5 宽度2 非空子孙数6 度为2的数目2 度为1的数目2查找5,成功,查找的元素为E删除E后,以广义表形式打印A(B(C,D(,F)))输入二:ABD□□EH□□□CF□G□□□(以□表示空格),查找10,删除B预测结果:先序遍历ABDEHCFG中序遍历DBHEAGFC后序遍历DHEBGFCA层次遍历ABCDEFHG广义表打印A(B(D,E(H)),C(F(,G)))叶子数3 深度4 宽度3 非空子孙数7 度为2的数目2 度为1的数目3查找10,失败。

数据结构实验报告——树

数据结构实验报告——树

2008级数据结构实验报告实验名称:实验三树学生姓名:班级:班内序号:学号:日期:2009年11月23日1.实验要求a. 实验目的通过选择两个题目之一进行实现,掌握如下内容:掌握二叉树基本操作的实现方法了解赫夫曼树的思想和相关概念学习使用二叉树解决实际问题的能力b. 实验内容利用二叉树结构实现赫夫曼编/解码器。

基本要求:1、初始化(Init):能够对输入的任意长度的字符串s进行统计,统计每个字符的频度,并建立赫夫曼树2、建立编码表(CreateTable):利用已经建好的赫夫曼树进行编码,并将每个字符的编码输出。

3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出。

4、译码(Decoding):利用已经建好的赫夫曼树对编码后的字符串进行译码,并输出译码结果。

5、打印(Print):以直观的方式打印赫夫曼树(选作)6、计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫曼编码的压缩效果。

2. 程序分析2.1 存储结构存储结构:二叉树示意图如下:2.2 关键算法分析核心算法思想:1.哈夫曼编码(Huffman Coding)是可变字长编码。

编码时借助哈夫曼树,也即带权路径长度最小的二叉树,来建立编码。

2.哈夫曼编码可以实现无损数据压缩。

单个字符用一个特定长度的位序列替代:在字符串中出现频率高的符号,使用短的位序列,而那些很少出现的符号,则用较长的位序列。

关键算法思想描述和实现:关键算法1:统计字符出现的频度,记录出现的字符及其权值,对未出现的字符不予统计编码。

将统计的叶子节点编制成数组。

为创建哈夫曼树作准备。

C++实现:for(int i=0;str[i]!='\0';i++) //统计频度frequency[(short)str[i]]++;此处以一个一维的下标表示ascII编码,以元素之表示字符频度,解决统计字符的问题。

for(int j=0;j<128;j++) //统计叶子节点个数if(frequency[j]!=0) leaf++;此处扫描一遍上面建立的数组得到叶子节点的个数,则由(leaf*2-1)得到总的节点个数。

数据结构实验报告-树(二叉树)

数据结构实验报告-树(二叉树)

实验5:树(二叉树)(采用二叉链表存储)一、实验项目名称二叉树及其应用二、实验目的熟悉二叉树的存储结构的特性以及二叉树的基本操作。

三、实验基本原理之前我们都是学习的线性结构,这次我们就开始学习非线性结构——树。

线性结构中结点间具有唯一前驱、唯一后继关系,而非线性结构中结点的前驱、后继的关系并不具有唯一性。

在树结构中,节点间关系是前驱唯一而后继不唯一,即结点之间是一对多的关系。

直观地看,树结构是具有分支关系的结构(其分叉、分层的特征类似于自然界中的树)。

四、主要仪器设备及耗材Window 11、Dev-C++5.11五、实验步骤1.导入库和预定义2.创建二叉树3.前序遍历4.中序遍历5.后序遍历6.总结点数7.叶子节点数8.树的深度9.树根到叶子的最长路径10.交换所有节点的左右子女11.顺序存储12.显示顺序存储13.测试函数和主函数对二叉树的每一个操作写测试函数,然后在主函数用while+switch-case的方式实现一个带菜单的简易测试程序,代码见“实验完整代码”。

实验完整代码:#include <bits/stdc++.h>using namespace std;#define MAX_TREE_SIZE 100typedef char ElemType;ElemType SqBiTree[MAX_TREE_SIZE];struct BiTNode{ElemType data;BiTNode *l,*r;}*T;void createBiTree(BiTNode *&T){ElemType e;e = getchar();if(e == '\n')return;else if(e == ' ')T = NULL;else{if(!(T = (BiTNode *)malloc(sizeof (BiTNode)))){cout << "内存分配错误!" << endl;exit(0);}T->data = e;createBiTree(T->l);createBiTree(T->r);}}void createBiTree2(BiTNode *T,int u) {if(T){SqBiTree[u] = T->data;createBiTree2(T->l,2 * u + 1);createBiTree2(T->r,2 * u + 2); }}void outputBiTree2(int n){int cnt = 0;for(int i = 0;cnt <= n;i++){cout << SqBiTree[i];if(SqBiTree[i] != ' ')cnt ++;}cout << endl;}void preOrderTraverse(BiTNode *T) {if(T){cout << T->data;preOrderTraverse(T->l);preOrderTraverse(T->r);}}void inOrderTraverse(BiTNode *T) {if(T){inOrderTraverse(T->l);cout << T->data;inOrderTraverse(T->r);}}void beOrderTraverse(BiTNode *T){if(T){beOrderTraverse(T->l);beOrderTraverse(T->r);cout << T->data;}}int sumOfVer(BiTNode *T){if(!T)return 0;return sumOfVer(T->l) + sumOfVer(T->r) + 1;}int sumOfLeaf(BiTNode *T){if(!T)return 0;if(T->l == NULL && T->r == NULL)return 1;return sumOfLeaf(T->l) + sumOfLeaf(T->r);}int depth(BiTNode *T){if(!T)return 0;return max(depth(T->l),depth(T->r)) + 1;}bool LongestPath(int dist,int dist2,vector<ElemType> &ne,BiTNode *T) {if(!T)return false;if(dist2 == dist)return true;if(LongestPath(dist,dist2 + 1,ne,T->l)){ne.push_back(T->l->data);return true;}else if(LongestPath(dist,dist2 + 1,ne,T->r)){ne.push_back(T->r->data);return true;}return false;}void swapVer(BiTNode *&T){if(T){swapVer(T->l);swapVer(T->r);BiTNode *tmp = T->l;T->l = T->r;T->r = tmp;}}//以下是测试程序void test1(){getchar();cout << "请以先序次序输入二叉树结点的值,空结点用空格表示:" << endl; createBiTree(T);cout << "二叉树创建成功!" << endl;}void test2(){cout << "二叉树的前序遍历为:" << endl;preOrderTraverse(T);cout << endl;}void test3(){cout << "二叉树的中序遍历为:" << endl;inOrderTraverse(T);cout << endl;}void test4(){cout << "二叉树的后序遍历为:" << endl;beOrderTraverse(T);cout << endl;}void test5(){cout << "二叉树的总结点数为:" << sumOfVer(T) << endl;}void test6(){cout << "二叉树的叶子结点数为:" << sumOfLeaf(T) << endl; }void test7(){cout << "二叉树的深度为:" << depth(T) << endl;}void test8(){int dist = depth(T);vector<ElemType> ne;cout << "树根到叶子的最长路径:" << endl;LongestPath(dist,1,ne,T);ne.push_back(T->data);reverse(ne.begin(),ne.end());cout << ne[0];for(int i = 1;i < ne.size();i++)cout << "->" << ne[i];cout << endl;}void test9(){swapVer(T);cout << "操作成功!" << endl;}void test10(){memset(SqBiTree,' ',sizeof SqBiTree);createBiTree2(T,0);cout << "操作成功!" << endl;}void test11(){int n = sumOfVer(T);outputBiTree2(n);}int main(){int op = 0;while(op != 12){cout << "-----------------menu--------------------" << endl;cout << "--------------1:创建二叉树--------------" << endl;cout << "--------------2:前序遍历----------------" << endl;cout << "--------------3:中序遍历----------------" << endl;cout << "--------------4:后序遍历----------------" << endl;cout << "--------------5:总结点数----------------" << endl;cout << "--------------6:叶子节点数--------------" << endl;cout << "--------------7:树的深度----------------" << endl;cout << "--------------8:树根到叶子的最长路径----" << endl;cout << "--------------9:交换所有节点左右子女----" << endl;cout << "--------------10:顺序存储---------------" << endl;cout << "--------------11:显示顺序存储-----------" << endl;cout << "--------------12:退出测试程序-----------" << endl;cout << "请输入指令编号:" << endl;if(!(cin >> op)){cin.clear();cin.ignore(INT_MAX,'\n');cout << "请输入整数!" << endl;continue;}switch(op){case 1:test1();break;case 2:test2();break;case 3:test3();break;case 4:test4();break;case 5:test5();break;case 6:test6();break;case 7:test7();break;case 8:test8();break;case 9:test9();break;case 10:test10();break;case 11:test11();break;case 12:cout << "测试结束!" << endl;break;default:cout << "请输入正确的指令编号!" << endl;}}return 0;}六、实验数据及处理结果测试用例:1.创建二叉树(二叉链表形式)2.前序遍历3.中序遍历4.后序遍历5.总结点数6.叶子结点数7.树的深度8.树根到叶子的最长路径9.交换所有左右子女10.顺序存储七、思考讨论题或体会或对改进实验的建议通过这次实验,我掌握了二叉树的顺序存储和链式存储,体会了二叉树的存储结构的特性,掌握了二叉树的树上相关操作。

北邮数据结构实验报告

北邮数据结构实验报告

北邮数据结构实验报告北邮数据结构实验报告一、引言数据结构是计算机科学中的重要基础知识,对于计算机程序的设计和性能优化起着至关重要的作用。

本报告旨在总结北邮数据结构实验的相关内容,包括实验目的、实验设计、实验过程和实验结果等。

二、实验目的本次实验旨在通过实践操作,加深对数据结构的理解和应用能力。

具体目的如下:1. 掌握线性表、栈和队列等基本数据结构的实现方法;2. 熟悉二叉树、图等非线性数据结构的构建和遍历算法;3. 学会使用递归和非递归算法解决实际问题;4. 培养编程实践能力和团队合作意识。

三、实验设计本次实验包括以下几个部分:1. 线性表实验:设计一个线性表类,实现线性表的基本操作,如插入、删除和查找等。

通过实验,了解线性表的顺序存储和链式存储结构的特点和应用场景。

2. 栈和队列实验:设计栈和队列类,实现栈和队列的基本操作,如入栈、出栈、入队和出队等。

通过实验,掌握栈和队列的应用,如括号匹配、迷宫求解等。

3. 二叉树实验:设计二叉树类,实现二叉树的创建、遍历和查找等操作。

通过实验,熟悉二叉树的前序、中序和后序遍历算法,并了解二叉树的应用,如表达式求值等。

4. 图实验:设计图类,实现图的创建、遍历和最短路径等操作。

通过实验,掌握图的邻接矩阵和邻接表表示方法,并了解图的深度优先搜索和广度优先搜索算法。

四、实验过程1. 线性表实验:根据实验要求,首先选择线性表的存储结构,然后设计线性表类,实现插入、删除和查找等基本操作。

在实验过程中,遇到了一些问题,如边界条件的处理和内存管理等,通过团队合作,最终解决了这些问题。

2. 栈和队列实验:根据实验要求,设计栈和队列类,实现入栈、出栈、入队和出队等基本操作。

在实验过程中,我们发现了栈和队列在实际应用中的重要性,如括号匹配和迷宫求解等,通过实验加深了对栈和队列的理解。

3. 二叉树实验:根据实验要求,设计二叉树类,实现二叉树的创建、遍历和查找等操作。

在实验过程中,我们发现了二叉树在表达式求值和排序等方面的应用,通过实验加深了对二叉树的理解。

数据结构实验报告(二叉树的基本操作)

数据结构实验报告(二叉树的基本操作)
else if((root->LChild==NULL)&&(root->RChild==NULL)) LeafNum=1;
else LeafNum=LeafCount(root->LChild)+LeafCount(root->RChild);
//叶子数为左右子树数目之和
return LeafNum;
printf("\n菜单选择\n\n");
printf(" 1.树状输出二叉树2.先序遍历二叉树\n");
printf(" 3.中序遍历二叉树4.后序遍历二叉树\n");
printf(" 5.输出叶子结点6.输出叶子结点的个数\n");
printf(" 7.输出二叉树的深度8.退出\n");
printf("\n----------------------------------------------------------------------\n");
{
printf("\n\n");
j=j+1; k=0;
while(k<nlocate)
{
printf(" ");
k++;
}
}
while(k<(nlocate-1))
{
printf(" ");
k++;
}
printf("%c",bt->data );
q.front=q.front+1;
if(bt->LChild !=NULL)//存在左子树,将左子树根节点入队列

实验报告 实验三 二叉排序树的建立和查找

实验报告 实验三 二叉排序树的建立和查找

实验三二叉排序树的建立和查找一、实验目的1.掌握二叉排序树的建立算法2.掌握二叉排序树查找算法。

二、实验环境操作系统和C语言系统三、预习要求复习二叉排序树的生成及查找算法,编写完整的程序。

四、实验内容实现二叉排序树上的查找算法。

具体实现要求:用二叉链表做存储结构,输入键值序列,建立一棵二叉排序树并在二叉排序树上实现查找算法。

五、参考算法#include <stdio.h>#include <stdlib.h>typedef int InfoType;typedef int KeyType; /*假定关键字类型为整数*/typedef struct node /*结点类型*/{KeyType key; /*关键字项*/InfoType otherinfo; /*其它数据域,InfoType视应用情况而定,下面不处理它*/struct node *lchild,*rchild; /*左右孩子指针*/}BSTNode;typedef BSTNode *BSTree; /*BSTree是二叉排序树的类型*/BSTNode *SearchBST(BSTree T,KeyType key){ /*在二叉排序树T上查找关键字为key的结点,成功时返回该结点位置,否则返回NULL*/if(T==NULL||key==T->key) /*递归的终结条件*/return T; /*若T为空,查找失败;否则成功,返回找到的结点位置*/if(key<T->key)return SearchBST(T->lchild,key);elsereturn SearchBST(T->rchild,key); /*继续在右子树中查找*/}void InsertBST(BSTree *T,int key){ /*插入一个值为key的节点到二叉排序树中*/BSTNode *p,*q;if((*T)==NULL){ /*树为空树*/(*T)=(BSTree)malloc(sizeof(BSTNode));(*T)->key=key;(*T)->lchild=(*T)->rchild=NULL;}else{p=(*T);while(p){q=p;if(p->key>key)p=q->lchild;else if(p->key<key)p=q->rchild;else{printf("\n 该二叉排序树中含有关键字为%d的节点!\n",key);return;}}p=(BSTree)malloc(sizeof(BSTNode));p->key=key;p->lchild=p->rchild=NULL;if(q->key>key)q->lchild=p;elseq->rchild=p;}}BSTree CreateBST(void){ /*输入一个结点序列,建立一棵二叉排序树,将根结点指针返回*/BSTree T=NULL; /*初始时T为空树*/KeyType key;scanf("%d",&key); /*读入一个关键字*/while(key){ /*假设key=0是输入结束标志*/ InsertBST(&T,key); /*将key插入二叉排序树T*/scanf("%d",&key); /*读入下一关键字*/}return T; /*返回建立的二叉排序树的根指针*/ }void ListBinTree(BSTree T) /*用广义表示二叉树*/{if(T!=NULL){printf("%d",T->key);if(T->lchild!=NULL||T->rchild!=NULL){printf("(");ListBinTree(T->lchild);if(T->rchild!=NULL)printf(",");ListBinTree(T->rchild);printf(")");}}}void main(){BSTNode *SearchBST(BSTree T,KeyType key);void InsertBST(BSTree *Tptr,KeyType key);BSTree CreateBST();void ListBinTree(BSTree T);BSTree T;BSTNode *p;int key;printf("请输入关键字(输入0为结束标志):\n");T=CreateBST();ListBinTree(T);printf("\n");printf("请输入欲查找关键字:");scanf("%d",&key);p=SearchBST(T,key);if(p==NULL)printf("没有找到%d!\n",key);elseprintf("找到%d!\n",key);ListBinTree(p);printf("\n");}实验中出现的问题及对问题的解决方案输入数据时,总是不能得到结果,原因是在建立二叉树函数定义中,是对指针的值进行了修改。

数据结构二叉树实验报告

数据结构二叉树实验报告

实验三二叉树的遍历一、实验目的1、熟悉二叉树的结点类型和二叉树的基本操作。

2、掌握二叉树的前序、中序和后序遍历的算法。

3、加深对二叉树的理解,逐步培养解决实际问题的编程能力。

二、实验环境运行C或VC++的微机。

三、实验内容1、依次输入元素值,以链表方式建立二叉树,并输出结点的值。

2、分别以前序、中序和后序遍历二叉树的方式输出结点内容。

四、设计思路1. 对于这道题,我的设计思路是先做好各个分部函数,然后在主函数中进行顺序排列,以此完成实验要求2.二叉树采用动态数组3.二叉树运用9个函数,主要有主函数、构建空二叉树函数、建立二叉树函数、访问节点函数、销毁二叉树函数、先序函数、中序函数、后序函数、范例函数,关键在于访问节点五、程序代码#include <stdio.h>#include <stdlib.h>#include <malloc.h>#define OK 1#define ERROR 0typedef struct TNode//结构体定义{-int data; //数据域struct TNode *lchild,*rchild; // 指针域包括左右孩子指针}TNode,*Tree;void CreateT(Tree *T)//创建二叉树按,依次输入二叉树中结点的值{int a;scanf("%d",&a);if(a==00) // 结点的值为空*T=NULL;else // 结点的值不为空{*T=(Tree)malloc(sizeof(TNode));if(!T){printf("分配空间失败!!TAT");exit(ERROR);}(*T)->data=a;CreateT(&((*T)->lchild)); // 递归调用函数,构造左子树CreateT(&((*T)->rchild)); // 递归调用函数,构造右子树}}void InitT(Tree *T)//构建空二叉树{T=NULL;}void DestroyT(Tree *T)//销毁二叉树{if(*T) // 二叉树非空{DestroyT(&((*T)->lchild)); // 递归调用函数,销毁左子树DestroyT(&((*T)->rchild)); // 递归调用函数,销毁右子树free(T);T=NULL;}}void visit(int e)//访问结点{printf("%d ",e);}-void PreOrderT(Tree *T,void(*visit)(int))//先序遍历T{if(*T) // 二叉树非空{visit((*T)->data); // 先访问根结点PreOrderT(&((*T)->lchild),visit); // 递归调用函数,先序遍历左子树PreOrderT(&((*T)->rchild),visit); // 递归调用函数,先序遍历右子树}}void InOrderT(Tree *T,void(*visit)(int)){if(*T){InOrderT(&((*T)->lchild),visit); // 递归调用函数,中序遍历左子树visit((*T)->data); // 访问根结点InOrderT(&((*T)->rchild),visit); // 递归调用函数,中序遍历右子树}}void PostOrderT(Tree *T,void(*visit)(int)){if(*T){PostOrderT(&((*T)->lchild),visit); // 递归调用函数,后序遍历左子树PostOrderT(&((*T)->rchild),visit); // 递归调用函数,序遍历右子树visit((*T)->data); // 访问根结点}}void example(){int i;printf("如果你想建立如图所示的二叉树\n");printf("\n");printf(" 1 \n");printf(" / \\ \n");printf(" 3 3 \n");printf(" / \\ \\ \n");printf(" 4 5 7 \n");printf("\n");printf("请输入:1 3 4 00 00 5 00 00 3 00 7 00 00\n");printf("\n按先序次序输入二叉树中结点的值(输入00表示节点为空)\n");for(i=0;i<71;i++)printf("*");printf("\n");}int main (){Tree T;printf("**************欢迎使用!**************潘俊达\n"); example();printf("\n请输入所要建立的二叉树:\n");CreateT(&T);InitT(&T);int i;printf("先序遍历二叉树:\n");PreOrderT(&T,visit);printf("\n");printf("\n中序遍历二叉树:\n");InOrderT(&T,visit);printf("\n");printf("\n后序遍历二叉树:\n");PostOrderT(&T,visit);printf("\n");system("PAUSE");return 0;}六、程序截图1.范例函数显示,并输入先序二叉树节点值2.先序遍历二叉树3.中序遍历二叉树3.后序遍历二叉树。

北邮数据结构实验报告3二叉树含源码

北邮数据结构实验报告3二叉树含源码

数据结构实验报告实验名称:实验三——树题目一学生姓名:申宇飞班级:2012211103班内序号:03学号:2012210064日期:2013年12月3日1.实验要求掌握二叉树基本操作的实现方法根据二叉树的抽象数据类型的定义,使用二叉链表实现一个二叉树。

二叉树的基本功能:1、二叉树的建立2、前序遍历二叉树3、中序遍历二叉树4、后序遍历二叉树5、按层序遍历二叉树6、求二叉树的深度7、求指定结点到根的路径8、二叉树的销毁9、其他:自定义操作编写测试main()函数测试线性表的正确性2. 程序分析2.1 存储结构采用二叉树的存储结构,其中每个二叉树的结点定义了一个结构体,该结构体包含三个元素,分别是一个T类型的数据域data,一个指向T类型的指针左孩子,一个指向T 类型的指针右孩子,示意图如图所示。

采用了队列的存储结构。

示意图如图所示:对于二叉树中每个结点的data 域的赋值,我们事先把这些data 储存在一个数组中,通过对数组元素的调用事先对二叉树中每个结点的data 域的赋值。

2.2 关键算法分析 一:二叉树的建立: A . 自然语言描述:1首先判断调用的数组是否为空,如果为空,直接将一个已经初始化好的根节点置为空。

2 如果该数组不为空,则把调用的数组的第一个元素的赋给根节点的data 域。

3 采用递归的思想,分别将根节点的左右孩子作为根节点,递归调用该函数。

完成对左右子树的赋值。

B . 代码详细分析:template <class T> void BiTree<T>::Create(Node<T> *&R,T* buf,int i) {if (buf[i-1]==0) R = NULL; else {R=new Node<T>; R->data = buf[i-1];Create(R->lch, buf, 2*i); Create(R->rch, buf, 2*i+1); }lchdata rchlchdata rchlchdata rchlchdata rchlchdata rchlchdata rchlch data rchA[2*i]A[2*i+1] lch data rch lch data rch二:前序遍历二叉树:A. 自然语言描述:1:建立栈2:判断该栈是否为空并且根节点是否为空指针3:如果根节点不是空指针,则输出它的data域,并且是它入栈4:入栈后将根节点指针指向它的左孩子5:如果根节点是空指针6:则根节点出栈,并且指向根节点的指针指向它的右孩子B.代码详细分析:template <class T> void BiTree<T>::Preorder(Node<T> *R){Stack<Node<T>*> S;while(!S.IsEmpty() || (R!=NULL)){if (R!=NULL){Print(R->data);S.Push(R);R=R->lch;}else{R=S.Pop();R=R->rch;}}}三:中序遍历二叉树:A.自然语言描述:1:建立栈2:判断该栈是否为空并且根节点是否为空指针3:如果根节点不是空指针,将它入栈4:入栈后将根节点指针指向它的左孩子5:如果根节点是空指针6:则根节点出栈,输出该节点的data域,并且指向根节点的指针指向它的右孩子B. 代码详细分析:template <class T> void BiTree<T>::Inorder(Node<T> *R){Stack<Node<T>*> S;while(!S.IsEmpty() || (R!=NULL)){if (R!=NULL){S.Push(R);R=R->lch;}else{R=S.Pop();Print(R->data);R=R->rch;}}}四:后序遍历二叉树:A.自然语言描述:1:判断根节点是否为空2:如果根节点不为空3:递归调用后续遍历函数,函数的参数改为根节点的左孩子 4:递归调用后续遍历函数,函数的参数改为根节点的右孩子 5:输出根节点的data域B.代码详细分析:template <class T> void BiTree<T>::Postorder(Node<T> *R) {if (R!=NULL) {Postorder(R->lch);Postorder(R->rch);Print(R->data);}}}}123五:层序遍历二叉树:A.自然语言描述:1:判断根节点是否为空2:如果根节点不为空3:输出根节点的data域4:递归调用层续遍历函数,函数的参数改为根节点的左孩子5:递归调用层序遍历函数,函数的参数改为跟结点的右孩子B.代码详细分析:template <class T> void BiTree<T>::Levelorder(Node<T> *R){Queue<Node<T>*> Q;while(!Q.IsEmpty() || (R!=NULL)){if (R!=NULL){Print(R->data);Q.EnQueue(R->lch);Q.EnQueue(R->rch);}R=Q.DelQueue();}}}123六:求二叉树的深度:A.自然语言描述:1:判断根节点是否为空,如果根节点为空,返回02:如果根节点不为空但是根节点的左右孩子同时为空,返回13:如果以上两个条件都不成立4:递归调用求二叉树的深度,函数的参数改为根节点的左孩子,并且深度初始化为1 5:递归调用求二叉树的深度,函数的参数改为跟结点的右孩子,并且深度初始化为0 6:返回4与5步中得出深度较大的那个数作为二叉树的深度数B.代码详细分析:template <class T> int BiTree<T>::GetDepth(Node<T> *R,int d){if (R==NULL) return d;if ((R->lch==NULL) && (R->rch==NULL))return d+1;else{int m = GetDepth(R->lch,d+1); int n = GetDepth(R->rch,d+1); return n>m? n:m; } }七:二叉树的销毁 A.自然语言描述:1:判断根节点是否为空 2:如果根节点不为空3:递归调用二叉树的销毁函数,参数改为根节点的左孩子 4:递归调用二叉树的销毁函数,参数改为根节点的右孩子 5:释放根节点指向的内存 B.代码详细分析:template <class T> void BiTree<T>::Destroy(Node<T> *R) {if (R!=NULL) { Destroy(R->lch); Destroy(R->rch); delete R; } }}:123八:求二叉树的叶子结点数: A.自然语言描述:1:判断根节点是否为空,如果为空,返回02:如果根节点不为空,切根节点的左右孩子同时为空,返回13:递归调用求二叉树的叶子节点数函数,参数改为根节点的左孩子 4:递归调用求二叉树的叶子结点数函数,参数改为根节点的右孩子 5:返回根节点的左右子树的叶子结点数之和 B.代码详细分析:template <class T> int BiTree<T>::LeafNodeCount(Node<T> *R) {if (R==NULL) return 0;if ((R->lch==NULL) && (R->rch==NULL)) return 1; else {int n=LeafNodeCount(R->lch); int m=LeafNodeCount(R->rch); return m+n; } }九:求二叉树的结点数: A.自然语言描述:} }123}1231:判断根节点是否为空,如果为空,返回02:如果根节点不为空3:递归调用求二叉树的结点数的函数,参数改为根节点的左孩子4:递归调用求二叉树的结点数的函数,参数改为根节点的右孩子5:返回根节点的左右字数的结点数之和B.代码详细分析:template <class T> int BiTree<T>::NodeCount(Node<T> *R){if (R==NULL) return 0;else{int m=NodeCount(R->lch);}}int n=NodeCount(R->rch); return m+n+1;}1232.3 其他对二叉树的操作上,前序遍历与中序遍历采用了非递归算法,后续遍历,层序遍历,求二叉树深度,求二叉树叶子结点数,求二叉树结点数等函数采用了递归算法。

北信-实验三-二叉树

北信-实验三-二叉树

实验报告课程名称数据结构实验项目二叉树的建立与遍历实验仪器PC系别:计算机科学与技术班级\学号:计科0902/2009011136姓名:高锋日期:2011.04成绩:指导老师:X 仰森一、目的和要求:1、熟练掌握二叉树的定义、性质和存储结构;2、熟练掌握二叉树的三种遍历和线索化以与遍历算法的各种描述形式;3、学会编写实现树的各种操作的算法。

二、实验题目:二叉树的建立与遍历:掌握建立二叉树的方法,实现先序、中序、后序三种遍历(递归和非递归)算法;三、源程序(递归和非递归遍历)#include<stdio.h>#include<stdlib.h>#define TRUE 1#define FALSE 0//树节点结构体typedef struct TNode{char data;struct TNode *lc,*rc;}*Tree;//栈结构体typedef struct Stack{Tree *top,*base; //元素为树节点指针的指针!int stacksize;}stack;//栈的初始化void InitStack(stack &s){// printf("init\n");s.base=(Tree *)malloc(sizeof(TNode)*100);//初始化100个空间if(!s.base){printf("error!\n");return;}s.top=s.base;s.stacksize=0;}//压栈操作void push(stack &s,Tree t){*s.top = t;// printf("push %c\n",(*s.top)->data);s.top++; //栈顶指针+1s.stacksize++;}//出栈操作Tree pop(stack &s){// Tree *p;if(s.top==s.base) //判断是否为空栈{printf("stack empty error!\n");return NULL;}s.stacksize--;// p=s.top-1;// printf("pop %c\n",(*p)->data);return *(--s.top); //返回栈顶元素:树节点指针}//获得栈顶元素Tree getTop(stack &s){if(s.top==s.base)return NULL;return *(s.top-1);}//判断是否为空栈的函数int stackEmpty(stack &s){// printf("stackempty\n");if(s.top==s.base)return TRUE;elsereturn FALSE;}//构造二叉树:递归先序创建void createTree(Tree &T){// printf("createtree\n");char ch;scanf("%c",&ch);if(ch==' ') //空格代表空节点T = NULL;else{T=(Tree)malloc(sizeof(TNode));T->data = ch;createTree(T->lc); //创建左子树createTree(T->rc); //创建右子树}}//访问树节点void visit(Tree T){// printf("visit\n");if(T!=NULL)printf("%c ",T->data); //打印data else{printf("NULL ERROR!\n");return;}}//递归先序void PreOrder(Tree T){if(T==NULL)return;else{printf("%c ",T->data);PreOrder(T->lc);PreOrder(T->rc);}}//递归中序void InOrder(Tree T){if(T==NULL)return;else{InOrder(T->lc);printf("%c ",T->data);InOrder(T->rc);}}//递归后序void PostOrder(Tree T){if(T==NULL)return;else{PostOrder(T->lc);PostOrder(T->rc);printf("%c ",T->data);}}//先序遍历void preOrder(Tree T){stack s;InitStack(s); //初始化栈Tree t=T;while(t || !stackEmpty(s)){if(t){visit(t);push(s,t);t=t->lc;}//走到树的最左边同时进栈并且访问(先序){t=pop(s); //中间结点出栈t=t->rc; //右子树进栈}}}//中序遍历void inOrder(Tree T){// printf("inorder\n");stack s;InitStack(s);Tree t=T;while(t || !stackEmpty(s)) //t不为NULL即t为真时不再调用stackEmpty判断{if(t){push(s,t);t=t->lc;}//走到树的最左边,进栈{t=pop(s);//弹出相对的中间结点visit(t);//访问当前节点t=t->rc;//右子树进栈}}}//后序遍历hardvoid postOrder(Tree T){stack s;InitStack(s);Tree t=T;while(t || !stackEmpty(s))//循环结束条件{if(t){push(s,t);t=t->lc;}//走到最左边,进栈else{t=getTop(s); //获得栈顶元素if(t->rc!=NULL)//判断栈顶元素是否有右子树t=t->rc; //若有则右子树进栈else{do{t=pop(s);visit(t); //否则该节点可以弹出并且访问了}while(getTop(s) && t == getTop(s)->rc);//直到栈顶为空或当前弹出元素不为栈顶元素右子树(这里更郁闷)if(getTop(s)) //判断getTop(s)是否为空,否则会出错滴(这里好郁闷)t=getTop(s)->rc; //t为栈顶元素右子树,右子树接下来进栈elset=NULL;//提供整个循环结束条件}}}}//此程序二叉树的基本模型为左子树为空,只有右子树的二叉树//当左子树被访问之后,即可认为该左子树为空//后序遍历难点:(需要判断当前节点和parent节点的关系)//当前弹出(可visit)节点若为栈顶(parent)左子树,//则可直接转向右子树,使右子树进栈//若为栈顶(parent)右子树,则得连续出栈,直到当前节点为parent左子树或栈顶为空//主函数,各种调用int main(){Tree T=NULL;printf("请先序输入二叉树:(空格代表空树)\n");createTree(T);printf("前序序列(递归):\n");PreOrder(T);printf("\n");printf("前序序列(非递归):\n");preOrder(T);printf("\n");printf("中序序列(递归):\n");InOrder(T);printf("\n");printf("中序序列(非递归):\n");inOrder(T);printf("\n");printf("后序序列(递归):\n");PostOrder(T);printf("\n");printf("后序序列(非递归):\n");postOrder(T);printf("\n");return 0;}运行结果:四.实验总结1、通过编写遍历程序,理解了二叉树的结构特点,掌握了一定的遍历规律。

算法与数据结构实验报告——树及其应用

算法与数据结构实验报告——树及其应用

北京邮电大学软件学院2019-2020学年第1学期实验报告课程名称:算法与数据结构课程设计实验名称:树及其应用实验完成人:日期: 2019 年 11月 10 日一、实验目的树是一种应用极为广泛的数据结构,也是这门课程的重点。

它们的特点在于非线性。

广义表本质上是树结构。

本章实验继续突出了数据结构加操作的程序设计观点,但根据这两种结构的非线性特点,将操作进一步集中在遍历操作上,因为遍历操作是其他众多操作的基础。

遍历逻辑的(或符号形式的)结构,访问动作可是任何操作。

本次实验希望帮助学生熟悉各种存储结构的特征,以及如何应用树结构解决具体问题(即原理与应用的结合)。

二、实验内容必做内容1)二叉树的建立与遍历[问题描述]建立一棵二叉树,并对其进行遍历(先序、中序、后序),打印输出遍历结果。

[基本要求]从键盘接受输入(先序),以二叉链表作为存储结构,建立二叉树(以先序来建立),并采用递归算法对其进行遍历(先序、中序、后序),将遍历结果打印输出。

[测试数据]ABCффDEфGффFффф(其中ф表示空格字符)则输出结果为先序:ABCDEGF中序:CBEGDFA后序:CGBFDBA2)打印二叉树结构[问题描述]按凹入表形式横向打印二叉树结构,即二叉树的根在屏幕的最左边,二叉树的左子树在屏幕的下边,二叉树的右子树在屏幕的上边。

例如:[测试数据]由学生依据软件工程的测试技术自己确定。

注意测试边界数据,如空二叉树。

[实现提示](1)利用RDL遍历方法;(2)利用结点的深度控制横向位置。

选做内容采用非递归算法实现二叉树遍历。

三、实验环境Windows下利用vs 2019完成,语言c++四、实验过程描述首先构造Tree类,内含树的结构体BiTree,以及本实验所要用到的一些操作typedef struct BiTNode{TElemType data;int degree, depth, level; //度,高度,高度差struct BiTNode* lchild, * rchild; /* 左右孩子指针 */}BiTNode, * BiTree;实现相应功能:1、二叉树的建立与遍历构造二叉树:前序构造,先赋值,然后递归构造左子树,递归构造右函数BiTNode* Tree::CreatBiTree(BiTree T) {TElemType ch;cin >> noskipws >> ch; //不跳过空格if (ch == ' ')T = NULL; //输入空格表示空子树else {T = new BiTNode; //分配空间if(!T) //分配失败就退出throw new std::bad_alloc;T->degree = 0; //记录度(T)->data = ch;T->depth++; //度增加T->lchild=CreatBiTree(T->lchild); //递归创建左子树T->rchild=CreatBiTree(T->rchild); //递归创建右子树if (T->lchild != NULL)T->degree++; //有一个孩子度就加一if (T->rchild != NULL)T->degree++;}return T;}销毁二叉树:后序递归销毁左右子树(需要先查找到子树,销毁再销毁父亲树)void Tree::Release(BiTree T) {if (T != NULL) {Release(T->lchild); //递归销毁左子树Release(T->rchild); //递归销毁右子树delete T;}}//前序遍历void Tree::PreOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) { if (T) /* T不空 */{(this->*Visit)(T); /* 先访问根结点 */PreOrderTraverse(T->lchild, Visit); /* 再先序遍历左子树 */PreOrderTraverse(T->rchild, Visit); /* 最后先序遍历右子树 */ }}//中序遍历void Tree::InOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) {if (T){InOrderTraverse(T->lchild, Visit); /* 先中序遍历左子树 */(this->*Visit)(T); /* 再访问根结点 */InOrderTraverse(T->rchild, Visit); /* 最后中序遍历右子树 */ }}//后序遍历void Tree::PostOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) {if (T){PostOrderTraverse(T->lchild, Visit); /* 先中序遍历左子树 */PostOrderTraverse(T->rchild, Visit); /* 最后中序遍历右子树 */(this->*Visit)(T); /* 再访问根结点 */}}//查找深度int Tree::TreeDepth(BiTree T) {int i, j;if (!T)return 0; /* 空树深度为0 */if (T->lchild)i = TreeDepth(T->lchild); /* i为左子树的深度 */elsei = 0;if (T->rchild)j = TreeDepth(T->rchild); /* j为右子树的深度 */elsej = 0;T->depth = i > j ? i + 1 : j + 1;return T->depth;}//得到层数void Tree::getLevel(BiTree T, int level){if (T){T->level = level;getLevel(T->lchild, level + 1); //得到左子树的层数,左子树根节点的层数比此节点多一getLevel(T->rchild, level + 1); //得到右子树的层数,右子树根节点的层数比此节点多一}}//非递归中序遍历void Tree::NoRecInOrderTraverse(BiTree T, void(Tree::*Visit)(BiTree)) {LinkedStack<BiTree> S;BiTree p = T;while (p || !S.isEmpty()) {if (p) {S.Push(p); //当节点不为空时就压栈,然后判断左孩子p = p->lchild;}else {p=S.Pop(); //返回到父节点(this->*Visit)(p); //访问p = p->rchild; //然后指向右节点}}}实验二:2、打印二叉树结构//中序遍历RDLvoid Tree::InOrderTraverseRDL(BiTree T, void(Tree::* Visit)(BiTree)) {if (T){InOrderTraverseRDL(T->rchild, Visit); /* 先中序遍历左子树 */(this->*Visit)(T); /* 再访问根结点 */InOrderTraverseRDL(T->lchild, Visit); /* 最后中序遍历右子树 */ }}//打印二叉树图形打印图形时,需要中序遍历RDL(先遍历右节点,再遍历右节点)。

北邮数据结构实验—二叉排序树

北邮数据结构实验—二叉排序树

数据结构实验报告实验名称:______二叉排序树___________ 学生姓名:____________________班级:_______________班内序号:_______________________学号:________________日期:________________1.实验要求根据二叉排序树的抽象数据类型的定义,使用二叉链表实现一个二叉排序树。

二叉排序树的基本功能:1.二叉排序树的建立2.二叉排序树的查找3.二叉排序树的插入4.二叉排序树的删除5.二叉排序树的销毁6.其他:自定义操作编写测试main()函数测试二叉排序树的正确性2. 程序分析2.1 存储结构二叉链表2.2 程序流程(或程序结构、或类关系图等表明程序构成的内容,一般为流程图等)2.2.1.2.2.2.伪代码1.从文件读取待建树元素2.建树,若待插入元素比根节点小,向左子树前进并重复比较左子树根节点,若待插入元素比根节点大,向右子树前进并重复比较右子树根节点,直至找到空节点则插入该元素,不断插入直至不剩下元素。

3.用户选择操作。

4.若用户选择查找,则现由用户输入待查找数值。

从根节点开始比较,若较小则移至左子树,若较大则移至右子树,直至关键码相等,则输出节点情况。

5.若用户选择插入,则现由用户输入待插入数值。

从根节点开始比较,若较小则移至左子树,若较大则移至右子树,直至到空节点,则插入该元素。

6.若用户选择删除,则现由用户输入待删除数值。

从根节点开始比较,若较小则移至左子树,若较大则移至右子树,直至关键码相等;1).若该节点为叶子节点,则直接删除;2).若该节点无左子树,则其双亲节点直接与其右子树根节点连接,再删除该节点;3).若该节点有左子树,则其左子树的最右节点数值直接覆盖该节点数值,再删除最后节点。

7.若用户选择销毁,则不断执行删除操作直至不剩余节点。

8.若用户选择退出,则程序结束。

2.3 关键算法分析关键代码即删除操作,代码如下:void Delete(BiNode* &R){BiNode* q=new BiNode;BiNode *s=new BiNode;if(R->lch==NULL){q=R;R=R->rch;delete q;}else if(R->rch==NULL){q=R;R=R->lch;delete q;}else{q=R;s=R->lch;while(s->rch!=NULL){q=s;s=s->rch;}R->data=s->data;if(q!=R)q->rch=s->lch;elseR->lch=s->lch;delete s;}}void Deletedata(BiNode* &R, int key){if(R==NULL) return;if(R->data==key) Delete(R);else if(R->data>key) Deletedata(R->lch,key);else Deletedata(R->rch,key);}首先先要定位到要删除的节点,不断递归调用deletedata这个函数,找到数值与需要删除节点的数值相等的节点时,调用delete这个函数。

数据结构二叉树实验报告(附代码)

数据结构二叉树实验报告(附代码)

一、【实验构思(Conceive)】(10%)(本部分应包括:描述实验实现的基本思路,包括所用到的离散数学、工程数学、程序设计、算法等相关知识)首先构造二叉树的存储结构,用data存储当前节点的值,分别用*lchild,*rchild 表示该节点的左右孩子。

然后应用BiTree Create函数,根据用户的输入构造二叉树,当输入#时表示没有孩子。

采用递归的思想构造Preorder,Inorder,Postorder函数,分别实现二叉树的先序,中序,和后序的遍历。

然后编写了Sumleaf,Depth函数,来求叶子节点的数目和二叉树的深度。

二、【实验设计(Design)】(20%)(本部分应包括:抽象数据类型的功能规格说明、主程序模块、各子程序模块的伪码说明,主程序模块与各子程序模块间的调用关系)二叉树的存储结构:typedef struct BiTNode{char data;struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;子程序模块:BiTree Create(BiTree T){char ch;ch=getchar();if(ch=='#')T=NULL;else{if(!(T=(BiTNode *)malloc(sizeof(BiTNode))))printf("Error!");T->data=ch;T->lchild=Create(T->lchild);T->rchild=Create(T->rchild);}return T;}void Preorder(BiTree T){if(T){printf("%c",T->data);Preorder(T->lchild);Preorder(T->rchild);}}int Sumleaf(BiTree T){int sum=0,m,n;if(T){if((!T->lchild)&&(!T->rchild)) sum++;m=Sumleaf(T->lchild);sum+=m;n=Sumleaf(T->rchild);sum+=n;}return sum;}void Inorder(BiTree T) {if(T){Inorder(T->lchild); printf("%c",T->data); Inorder(T->rchild); }}void Postorder(BiTree T) {if(T){Postorder(T->lchild); Postorder(T->rchild); printf("%c",T->data); }}int Depth(BiTree T){int dep=0,depl,depr;if(!T)dep=0;else{depl=Depth(T->lchild);depr=Depth(T->rchild);dep=1+(depl>depr?depl:depr);}return dep;}主程序模块:int main(){BiTree T = 0;int sum,dep;printf("请输入你需要建立的二叉树\n");printf("例如输入序列ABC##DE#G##F###(其中的#表示空)\n并且输入过程中不要加回车\n输入完之后可以按回车退出\n");T=Create(T);printf("先序遍历的结果是:\n");Preorder(T);printf("\n");printf("中序遍历的结果是:\n");Inorder(T);printf("\n");printf("后序遍历的结果是:\n");Postorder(T);printf("\n");printf("统计的叶子数:\n");sum=Sumleaf(T);printf("%d",sum);printf("\n统计树的深度:\n");dep=Depth(T);printf("\n%d\n",dep);}三、【实现描述(Implement)】(30%)(本部分应包括:抽象数据类型具体实现的函数原型说明、关键操作实现的伪码算法、函数设计、函数间的调用关系,关键的程序流程图等,给出关键算法的时间复杂度分析。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

2.1 存储结构
采用二叉树的存储结构,其中每个二叉树的结点定义了一个结构体,该结构体包 含三个元素,分别是一个 T 类型的数据域 data,一个指向 T 类型的指针左孩子, 一个指向 T 类型的指针右孩子,示意图如图所示。
第1页
北京邮电大学信息与通信工程学院
第6页
北京邮电大学信息与通信工程学院
}
if (R==NULL) return d; if ((R->lch==NULL) && (R->rch==NULL)) return d+1; else { int m = GetDepth(R->lch,d+1); int n = GetDepth(R->rch,d+1); return n>m? n:m; } 1
2
3
第7页
北京邮电大学信息与通信工程学院
八:求二叉树的叶子结点数: A.自然语言描述: 1:判断根节点是否为空,如果为空,返回 0 2:如果根节点不为空,切根节点的左右孩子同时为空,返回 1 3:递归调用求二叉树的叶子节点数函数,参数改为根节点的左孩子 4:递归调用求二叉树的叶子结点数函数,参数改为根节点的右孩子 5:返回根节点的左右子树的叶子结点数之和 B.代码详细分析: template <class T> int BiTree<T>::LeafNodeCount(Node<T> *R) { if (R==NULL) return 0; if ((R->lch==NULL) && (R->rch==NULL)) return 1; else { int n=LeafNodeCount(R->lch); int m=LeafNodeCount(R->rch); return m+n; } 1 }
2
3
六:求二叉树的深度: A.自然语言描述: 1:判断根节点是否为空,如果根节点为空,返回 0 2:如果根节点不为空但是根节点的左右孩子同时为空,返回 1 3:如果以上两个条件都不成立 4:递归调用求二叉树的深度,函数的参数改为根节点的左孩子,并且深度初始化 为1 5:递归调用求二叉树的深度,函数的参数改为跟结点的右孩子,并且深度初始化 为0 6:返回 4 与 5 步中得出深度较大的那个数作为二叉树的深度数 B.代码详细分析: template <class T> int BiTree<T>::GetDepth(Node<T> *R,int d) {
第3页
北京邮电大学信息与通信工程学院
}
三:中序遍历二叉树: A.自然语言描述: 1:建立栈 2:判断该栈是否为空并且根节点是否为空指针 3:如果根节点不是空指针,将它入栈 4:入栈后将根节点指针指向它的左孩子 5:如果根节点是空指针 6:则根节点出栈,输出该节点的 data 域,并且指向根节点的指针指向它的右孩子 B. 代码详细分析: template <class T> void BiTree<T>::Inorder(Node<T> *R) { Stack<Node<T>*> S; while(!S.IsEmpty() || (R!=NULL)) { if (R!=NULL) { S.Push(R); R=R->lch; } else { R=S.Pop(); Print(R->data); R=R->rch; } }
第4页
北京邮电大学信息与通信工程学院
}
四:后序遍历二叉树: A.自然语言描述: 1:判断根节点是否为空 2:如果根节点不为空 3:递归调用后续遍历函数,函数的参数改为根节点的左孩子 4:递归调用后续遍历函数,函数的参数改为根节点的右孩子 5:输出根节点的 data 域 B.代码详细分析: template <class T> void BiTree<T>::Postorder(Node<T> *R) { if (R!=NULL) { Postorder(R->lch); Postorder(R->rch); Print(R->data); } 1 }
第8页
北京邮电大学信息与通信工程学院
int n=NodeCount(R->rch); return m+n+1; } } 1
2
3
2.3 其他
对二叉树的操作上,前序遍历与中序遍历采用了非递归算法,后续遍历,层序遍历,求 二叉树深度,求二叉树叶子结点数,求二叉树结点数等函数采用了递归算法。为了提高运算 性能,可以将它们改为非递归算法来实现,例如,后续遍历的非递归算法如下: template <class T> void BiTreee<T>::Postorder (Node<T> *R) { Stack<SNode<T>*> S; SNode<T> *p; do { while (R!=NULL) { p->ptr=R; p->tag=1;S.Push(p); R=R->lch; } while(!S.IsEmpty() && S.GetTop()->tag==2) { p=S.Pop(); cout<<p->ptr->data; } if(!S.IsEmpty()) { S.GetTop()->tag=2; R=S.GetTop()->ptr->rch; } } while(!S.IsEmpty())
2
3
九:求二叉树的结点数: A.自然语言描述: 1:判断根节点是否为空,如果为空,返回 0 2:如果根节点不为空 3:递归调用求二叉树的结点数的函数,参数改为根节点的左孩子 4:递归调用求二叉树的结点数的函数,参数改为根节点的右孩子 5:返回根节点的左右字数的结点数之和 B.代码详细分析: template <class T> int BiTree<T>::NodeCount(Node<T> *R) { if (R==NULL) return 0; else { int m=NodeCount(R->lch);
3. 程序运行结果
主函数流程图如下:
第9页
北京邮电大学信息与通信工程学院
开始
初始化一个对象
初始化字符型数组,作为赋值准备
利用 creat 函数初始化一个二叉树,参数为初始化的字符型数组
执行前序,后序,中序,层序遍历,输出遍历结果
执行求结点数,叶子节点数,二叉树深度,路径函数
执行查找数中结点元素函数
结束
第 10 页
北京邮电大学信息与通信工程学院
程序运行截图如下:
4. 总结
对二叉树的操作上,前序遍历与中序遍历采用了非递归算法,后续遍历,层序遍历,求 二叉树深度,求二叉树叶子结点数,求二叉树结点数等函数采用了递归算法。为了提高运算 性能,可以将它们改为非递归算法来实现,对于比较复杂的算法,递归和非递归的运算时间 复杂度差别较大,从性能考虑,应当优先采用非递归算法
第2页
北京邮电大学信息与通信工程学院
Create(R->lch, buf, 2*i); Create(R->rch, buf, 2*i+1); } }
A[i-1]
lch
A[2*i]
data
rch
A[2*i+1]
lch
data
rch
lch
data
rch
重复上述赋值过程,实 现递归调用 二:前序遍历二叉树: A. 自然语言描述: 1:建立栈 2:判断该栈是否为空并且根节点是否为空指针 3:如果根节点不是空指针,则输出它的 data 域,并且是它入栈 4:入栈后将根节点指针指向它的左孩子 5:如果根节点是空指针 6:则根节点出栈,并且指向根节点的指针指向它的右孩子 B.代码详细分析: template <class T> void BiTree<T>::Preorder(Node<T> *R) { Stack<Node<T>*> S; while(!S.IsEmpty() || (R!=NULL)) { if (R!=NULL) { Print(R->data); S.Push(R); R=R->lch; } else { R=S.Pop(); R=R->rch; } }
第 11 页
北京邮电大学信息与通信工程学院
源代码
使用说明:新建头文件“Function.h”和代码文件“main.cpp”, 将以下两部分代码复制到相应的头文件和代码文件后 ctrl+F5 运行即 可
Function.h:
#include<iostream> using namespace std; template <class T> class Node { public: T data; Node<T>* lch; Node<T>* rch; int ltag; int rtag; Node():lch(NULL),rch(NULL),ltag(0),rtag(0){} }; template <class T> class stacknode { public: Node<T> * treenode; int tag; }; template <class T> class BiTree {
2.2 关键算法分析
一:二叉树的建立: A. 自然语言描述: 1 首先判断调用的数组是否为空,如果为空,直接将一个已经初始化好的根节点置 为空。 2 如果该数组不为空,则把调用的数组的第一个元素的赋给根节点的 data 域。 3 采用递归的思想,分别将根节点的左右孩子作为根节点,递归调用该函数。完成 对左右子树的赋值。 B. 代码详细分析: template <class T> void BiTree<T>::Create(Node<T> *&R,T* buf,int i) { if (buf[i-1]==0) R = NULL; else { R=new Node<T>; R->data = buf[i-1];
相关文档
最新文档