国家开放大学《数据结构》课程实验报告(实验4——二叉树)参考答案
- 格式:docx
- 大小:45.84 KB
- 文档页数:3
《数据结构》实验报告班级:学号:姓名:实验四二叉树的基本操作实验环境:Visual C++实验目的:1、掌握二叉树的二叉链式存储结构;2、掌握二叉树的建立,遍历等操作。
实验内容:通过完全前序序列创建一棵二叉树,完成如下功能:1)输出二叉树的前序遍历序列;2)输出二叉树的中序遍历序列;3)输出二叉树的后序遍历序列;4)统计二叉树的结点总数;5)统计二叉树中叶子结点的个数;实验提示://二叉树的二叉链式存储表示typedef char TElemType;typedef struct BiTNode{TElemType data;struct BiTNode *lchild,*rchild;}BiTNode,*BiTree;一、程序源代码#include <stdio.h>#include <stdlib.h>#define MAXSIZE 30typedef char ElemType;typedef struct TNode *BiTree;struct TNode {char data;BiTree lchild;BiTree rchild;};int IsEmpty_BiTree(BiTree *T) { if(*T == NULL)return 1;elsereturn 0;}void Create_BiTree(BiTree *T){char ch;ch = getchar();//当输入的是"#"时,认为该子树为空if(ch == '#')*T = NULL;//创建树结点else{*T = (BiTree)malloc(sizeof(struct TNode)); (*T)->data = ch; //生成树结点//生成左子树Create_BiTree(&(*T)->lchild);//生成右子树Create_BiTree(&(*T)->rchild);}}void TraverseBiTree(BiTree T) { //先序遍历if(T == NULL)return;else {printf("%c ",T->data);TraverseBiTree(T->lchild);TraverseBiTree(T->rchild);}}void InOrderBiTree(BiTree T) { //中序遍历if(NULL == T)return;else {InOrderBiTree(T->lchild);printf("%c ",T->data);InOrderBiTree(T->rchild);}}void PostOrderBiTree(BiTree T) {if(NULL == T)return;else {InOrderBiTree(T->lchild);InOrderBiTree(T->rchild);printf("%c ",T->data);}}int TreeDeep(BiTree T) {int deep = 0;if(T){int leftdeep = TreeDeep(T->lchild);int rightdeep = TreeDeep(T->rchild);deep = leftdeep+1 > rightdeep+1 ? leftdeep+1 : rightdeep+1;}return deep;}int Leafcount(BiTree T, int &num) {if(T){if(T->lchild ==NULL && T->rchild==NULL){num++;printf("%c ",T->data);}Leafcount(T->lchild,num);Leafcount(T->rchild,num);}return num;}void LevelOrder_BiTree(BiTree T){//用一个队列保存结点信息,这里的队列采用的是顺序队列中的数组实现 int front = 0;int rear = 0;BiTree BiQueue[MAXSIZE];BiTree tempNode;if(!IsEmpty_BiTree(&T)){BiQueue[rear++] = T;while(front != rear){//取出队头元素,并使队头指针向后移动一位tempNode = BiQueue[front++];//判断左右子树是否为空,若为空,则加入队列 if(!IsEmpty_BiTree(&(tempNode->lchild))) BiQueue[rear++] = tempNode->lchild;if(!IsEmpty_BiTree(&(tempNode->rchild))) BiQueue[rear++] = tempNode->rchild;printf("%c ",tempNode->data);}}}int main(void){BiTree T;BiTree *p = (BiTree*)malloc(sizeof(BiTree));int deepth,num=0 ;Create_BiTree(&T);printf("先序遍历二叉树:\n");TraverseBiTree(T);printf("\n");printf("中序遍历二叉树:\n");InOrderBiTree(T);printf("\n");printf("后序遍历二叉树:\n");PostOrderBiTree(T);printf("\n层次遍历结果:");LevelOrder_BiTree(T);printf("\n");deepth=TreeDeep(T);printf("树的深度为:%d",deepth);printf("\n");printf("树的叶子结点为:");Leafcount(T,num);printf("\\n树的叶子结点个数为:%d",num);return 0;}二、运行结果(截图)三、遇到的问题总结通过死循环的部分可以看出,在判断时是不能进入结点为空的语句中的,于是从树的构建中寻找问题,最终发现这一条语句存在着问题:这里给T赋值为空,也就是给整个结构体地址赋值为空,但是我们的目的是给该结构体中的内容,即左孩子的地址指向的内容赋为空。
数据结构上机实验报告题目:二叉树染色问题学生姓名:学生学号:学院名称:计算机学院专业:计算机科学与技术时间:目录第一章,需求分析31.1 原题描述31.2 详细问题的解决方案31.2.1 解决方案要求31.2.2 各个环节功能要求3第二章,概要设计52.1 抽象数据类型52.2 主要算法描述52.3 算法分析7第三章,详细设计83.1 程序代码8第四章,调试分析10第五章,测试分析11第六章,未来展望与思考12第一章需求分析1.1 原题描述一棵二叉树可以按照如下规则表示成一个由0、1、2组成的字符序列,我们称之为“二叉树序列S”:例如,下图所表示的二叉树可以用二叉树序列S=21200110来表示现在要对一棵二叉树的节点进行染色。
每个节点可以被染成红色、绿色或蓝色。
并且,一个节点与其子节点的颜色必须不同,如果该节点有两个子节点,那么这两个子节点的颜色也必须不相同。
给定一棵二叉树的二叉树序列,请求出这棵树中最多和最少有多少个点能够被染成绿色。
1.2详细问题的解决方案1.2.1 解决方案要求输入参数:输入数据由多组数据组成。
每组数据仅有一行,不超过10000个字符,表示一个二叉树序列。
输出参数:对于每组输入数据,输出仅一行包含两个整数,依次表示最多和最少有多少个点能够被染成绿色。
1.2.2 参考样例Sample Input1122002010Sample Output5 21.2.3 各个环节功能要求表1-2.1环节功能函数功能注意条件及限制规则CreatBitree() 先序建立二叉树字符’2’字符’1’字符’0’三种情况:,2,有左右子树;1,有左子树右空;0,左右子树为空PreOrder() 先序遍历二叉树以T是否为空遍历二叉树补充正文:由于只有三种颜色,可以用数字2,1,0分别表示,先序建立二叉树,将二叉树每个结点与其左孩子强行交叉赋值2与1(有右孩子的则赋予与结点和左孩子不同的值),即为按优先顺序2,1,0给节点赋值。
实验报告课程:数据结构(c语言)实验名称:二叉树的构建、基本操作和遍历系别:数字媒体技术实验日期:专业班级:媒体161 组别:无:学号:实验报告容验证性实验一、预习准备:实验目的:1、熟练掌握二叉树的结构特性,熟悉二叉树的各种存储结构的特点及适用围;2、熟练掌握二叉树的遍历方法及遍历算法;3、掌握建立哈夫曼树和哈夫曼编码的方法及带权路径长度的计算。
实验环境:Widows操作系统、VC6.0实验原理:1.定义:树:树(tree)是n(n>0)个结点的有限集T,其中,有且仅有一个特定的结点,称为树的根(root)。
当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2,……Tm,其中每一个集合本身又是一棵树,称为根的子树(subtree)二叉树:二叉树是n(n>=0)个结点的有限集,它或为空树(n=0),或由一个根结点和两棵分别称为左子树和右子树的互不相交的二叉树构成。
哈夫曼树: 最优二叉树——赫夫曼树设有n个权值{w1,w2,……wn},构造一棵有n个叶子结点的二叉树,每个叶子的权值为wi,则wpl最小的二叉树叫Huffman树。
2. 特点:树:树中至少有一个结点——根树中各子树是互不相交的集合二叉树:每个结点至多有二棵子树(即不存在度大于2的结点)二叉树的子树有左、右之分,且其次序不能任意颠倒哈夫曼树:一棵有n个叶子结点的Huffman树有2n-1个结点采用顺序存储结构——动态分配数组存储3. 表示:遍历二叉树:先序遍历:先访问根结点,然后分别先序遍历左子树、右子树中序遍历:先中序遍历左子树,然后访问根结点,最后中序遍历右子树后序遍历:先后序遍历左、右子树,然后访问根结点 按层次遍历:从上到下、从左到右访问各结点 构造Huffman 树的方法——Huffman 算法(1) 根据给定的n 个权值{w1,w2,……wn},构造n 棵只有根 结点的二叉树,令起权值为wj ;(2) 在森林中选取两棵根结点权值最小的树作左右子树,构造一棵新的二叉树,置新二叉树根结点权值为其左右子树根结点权值之和;(3) 在森林中删除这两棵树,同时将新得到的二叉树加入森林中重复上述两步,直到只含一棵树为止,这棵树即哈夫曼树。
实验报告四图的存储方式和应用(学科:数据结构)姓名单位班级学号实验日期成绩评定教师签名批改日期实验名称:实验四图的存储方式和应用4.1建立图的邻接矩阵【问题描述】根据图中顶点和边的信息编制程序建立图的邻接矩阵。
【基本要求】(1)程序要有一定的通用性。
(2)直接根据图中每个结点与其他结点的关联情况输入相关信息,程序能自动形成邻接矩阵【测试用例】【实现提示】(1)对图的顶点编号。
(2)在上图中,以顶点1为例,因为顶点2,3,4与顶点1关联,可以输入信息1 2 3 4,然后设法求出与顶点1关联的结点,从而求得邻接矩阵中相应与顶点1的矩阵元素。
实验图4-1【实验报告内容】设计程序代码如下:#include<stdio.h>#define MaxVertexNum 5#define MaxEdgeNum 20#define MaxValue 1000typedef int VertexType;typedef VertexType vexlist [MaxVertexNum];typedef int adjmatrix [MaxVertexNum] [MaxVertexNum];void Createl(vexlist Gv,adjmatrix GA,int n,int e){int i,j,k,w;printf("输入%d个顶点数据\n",n);for(i=0;i<n;i++) scanf("%d",&Gv[i]);for(i=0;i<n;i++)for(j=0;j<n;j++){if(i==j) GA[i][j]=0;else GA[i][j]=MaxValue;}Printf(“输入一条边的两端点序号i和j及边上的权w\n”);printf("输入%d条无向带权边\n",e);for(k=1;k<=e;k++){scanf("%d%d%d",&i,&j,&w);GA[i][j]=GA[j][i]=w;}}void main(){vexlist vl;adjmatrix a;Createl(vl,a,5,8);}。
数据结构二叉树实验报告二叉树是一种常用的数据结构,它在计算机科学中有着广泛的应用。
本文将介绍二叉树的定义、基本操作以及一些常见的应用场景。
一、二叉树的定义和基本操作二叉树是一种特殊的树形结构,它的每个节点最多有两个子节点。
一个节点的左子节点称为左子树,右子节点称为右子树。
二叉树的示意图如下:```A/ \B C/ \D E```在二叉树中,每个节点可以有零个、一个或两个子节点。
如果一个节点没有子节点,我们称之为叶子节点。
在上面的示例中,节点 D 和 E 是叶子节点。
二叉树的基本操作包括插入节点、删除节点、查找节点和遍历节点。
插入节点操作可以将一个新节点插入到二叉树中的合适位置。
删除节点操作可以将一个指定的节点从二叉树中删除。
查找节点操作可以在二叉树中查找指定的节点。
遍历节点操作可以按照一定的顺序遍历二叉树中的所有节点。
二、二叉树的应用场景二叉树在计算机科学中有着广泛的应用。
下面将介绍一些常见的应用场景。
1. 二叉搜索树二叉搜索树是一种特殊的二叉树,它的每个节点的值都大于其左子树中的节点的值,小于其右子树中的节点的值。
二叉搜索树可以用来实现快速的查找、插入和删除操作。
它在数据库索引、字典等场景中有着重要的应用。
2. 堆堆是一种特殊的二叉树,它的每个节点的值都大于或小于其子节点的值。
堆可以用来实现优先队列,它在任务调度、操作系统中的内存管理等场景中有着重要的应用。
3. 表达式树表达式树是一种用来表示数学表达式的二叉树。
在表达式树中,每个节点可以是操作符或操作数。
表达式树可以用来实现数学表达式的计算,它在编译器、计算器等场景中有着重要的应用。
4. 平衡二叉树平衡二叉树是一种特殊的二叉树,它的左子树和右子树的高度差不超过1。
平衡二叉树可以用来实现高效的查找、插入和删除操作。
它在数据库索引、自平衡搜索树等场景中有着重要的应用。
三、总结二叉树是一种常用的数据结构,它在计算机科学中有着广泛的应用。
本文介绍了二叉树的定义、基本操作以及一些常见的应用场景。
数据结构实验报告1. 实验目的和内容:掌握二叉树基本操作的实现方法2. 程序分析2.1存储结构链式存储2.程序流程2.3关键算法分析算法一:Create(BiNode<T>* &R,T data[],int i,int n)【1】算法功能:创建二叉树【2】算法基本思想:利用顺序存储结构为输入,采用先建立根结点,再建立左右孩子的方法来递归建立二叉链表的二叉树【3】算法空间时间复杂度分析:O(n)【4】代码逻辑:如果位置小于数组的长度则{ 创建根结点将数组的值赋给刚才创建的结点的数据域创建左子树,如果当前结点位置为i,则左孩子位置为2i创建右子树,如果当前结点位置为i,则右孩子位置为2i+1}否则R为空算法二:CopyTree(BiNode<T>*sR,BiNode<T>* &dR))【1】算法功能:复制构造函数【2】算法基本思想:按照先创建根结点,再递归创建左右子树的方法来实现。
【3】算法空间时间复杂度分析:O(n)【4】代码逻辑:如果源二叉树根结点不为空则{创建根结点调用函数自身,创建左子树调用函数自身,创建右子树}将该函数放在复制构造函数中调用,就可以实现复制构造函数算法三:PreOrder(BiNode<T>*R)【1】算法功能:二叉树的前序遍历【2】算法基本思想:这个代码用的是优化算法,提前让当前结点出栈。
【3】算法空间时间复杂度分析:O(n)【4】代码逻辑(伪代码)如果当前结点为非空,则{访问当前结点当前结点入栈将当前结点的左孩子作为当前结点}如果为空{则栈顶结点出栈则将该结点的右孩子作为当前结点}反复执行这两个过程,直到结点为空并且栈空算法四:InOrder(BiNode<T>*R)【1】算法功能:二叉树的中序遍历【2】算法基本思想:递归【3】算法空间时间复杂度分析:未知【4】代码逻辑:如果R为非空:则调用函数自身遍历左孩子访问该结点再调用自身访问该结点的右孩子算法五:LevelOrder(BiNode<T>*R)【1】算法功能:二叉树的层序遍历【2】算法基本思想:【3】算法空间时间复杂度分析:O(n)【4】代码逻辑(伪代码):如果队列不空{对头元素出队访问该元素若该结点的左孩子为非空,则左孩子入队;若该结点的右孩子为非空,则右孩子入队;}算法六:Count(BiNode<T>*R)【1】算法功能:计算结点的个数【2】算法基本思想:递归【3】算法空间时间复杂度分析:未知【4】代码逻辑:如果R不为空的话{调用函数自身计算左孩子的结点数调用函数自身计算右孩子的结点数}template<class T>int BiTree<T>::Count(BiNode<T>*R){if(R==NULL)return 0;else{int m=Count(R->lchild);int n=Count(R->rchild);return m+n+1;}}算法七:Release(BiNode<T>*R)【1】算法功能:释放动态内存【2】算法基本思想:左右子树全部释放完毕后再释放该结点【3】算法空间时间复杂度分析:未知【4】代码逻辑:调用函数自身,释放左子树调用函数自身,释放右子树释放根结点释放二叉树template<class T>void BiTree<T>::Release(BiNode<T>*R) {if(R!=NULL){Release(R->lchild);Release(R->rchild);delete R;}}template<class T>BiTree<T>::~BiTree(){Release(root);}int main(){BiTree<int> BTree(a,10);BiTree<int>Tree(BTree);BTree.PreOrder(BTree.root);cout<<endl;Tree.PreOrder(Tree.root);cout<<endl;BTree.InOrder(BTree.root);cout<<endl;Tree.InOrder(Tree.root);cout<<endl;BTree.PostOrder(BTree.root);cout<<endl;Tree.PostOrder(Tree.root);cout<<endl;BTree.LevelOrder(BTree.root);cout<<endl;Tree.LevelOrder(Tree.root);cout<<endl;int m=BTree.Count(BTree.root);cout<<m<<endl;return 0;}3.测试数据:int a[10]={1,2,3,4,5};1 2 4 5 31 2 4 5 34 25 1 34 5 2 3 11 2 3 4 554.总结:4.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.顺序存储七、思考讨论题或体会或对改进实验的建议通过这次实验,我掌握了二叉树的顺序存储和链式存储,体会了二叉树的存储结构的特性,掌握了二叉树的树上相关操作。