实验四 二叉树基本操作

合集下载

二叉树的基本操作

二叉树的基本操作

二叉树的基本操作二叉树是一种常见的数据结构,它由节点组成,每个节点最多有两个子节点。

二叉树在计算机领域中得到广泛应用,它的基本操作包括插入、删除、查找、遍历等。

1.插入操作:二叉树的插入操作是将一个新的节点添加到已有的二叉树中的过程。

插入操作会按照一定规则将新节点放置在正确的位置上。

插入操作的具体步骤如下:-首先,从根节点开始,比较新节点的值与当前节点的值的大小关系。

-如果新节点的值小于当前节点的值,则将新节点插入到当前节点的左子树中。

-如果新节点的值大于当前节点的值,则将新节点插入到当前节点的右子树中。

-如果当前节点的左子树或右子树为空,则直接将新节点插入到该位置上。

-如果当前节点的左子树和右子树都不为空,则递归地对左子树或右子树进行插入操作。

2.删除操作:二叉树的删除操作是将指定节点从二叉树中删除的过程。

删除操作有以下几种情况需要考虑:-如果待删除节点是叶子节点,则直接将其从二叉树中删除即可。

-如果待删除节点只有一个子节点,则将其子节点替换为待删除节点的位置即可。

-如果待删除节点有两个子节点,则需要找到其左子树或右子树中的最大节点或最小节点,将其值替换为待删除节点的值,然后再删除最大节点或最小节点。

3.查找操作:二叉树的查找操作是在二叉树中查找指定值的节点的过程。

查找操作的具体步骤如下:-从根节点开始,将待查找值与当前节点的值进行比较。

-如果待查找值等于当前节点的值,则返回该节点。

-如果待查找值小于当前节点的值,则在当前节点的左子树中继续查找。

-如果待查找值大于当前节点的值,则在当前节点的右子树中继续查找。

-如果左子树或右子树为空,则说明在二叉树中找不到该值。

4.遍历操作:二叉树的遍历操作是按照一定规则依次访问二叉树中的每个节点。

有三种常用的遍历方式:- 前序遍历(Preorder Traversal):先访问根节点,然后递归地前序遍历左子树和右子树。

- 中序遍历(Inorder Traversal):先递归地中序遍历左子树,然后访问根节点,最后递归地中序遍历右子树。

实验四 二叉树操作实现

实验四  二叉树操作实现

实验四二叉树操作实现
一、目的:
掌握二叉树的定义、性质及存储方式,各种遍历算法。

二、要求:
采用二叉树链表作为存储结构,完成二叉树的建立,先序、中序和后序以及按层次遍历的操作,求所有叶子及结点总数的操作。

三、实验内容
1、二叉树的基本操作。

2、调试程序,设计一棵二叉树,输入完全二叉树的先序序列,用#代表虚结点(空指针),
如ABD###CE##F##,建立二叉树,求出先序、中序和后序以及按层次遍历序列,求所有叶子及结点总数。

四、实验报告要求
要求所编的程序能正确运行,并提交实验报告。

实验报告的基本要求为:
1、陈述程序设计的任务,强调程序要做什么,明确规定:
(1)输入的形式和输出值的范围;
(2)输出的形式;
(3)程序所能达到的功能;
(4)测试数据:包括正确的输入输出结果和错误的输入及输出结果。

2、说明用到的数据结构定义、主程序的流程及各程序模块之间的调用关系。

3、提交带注释的源程序或者用伪代码写出每个操作所涉及的算法。

4、调试分析:
(1)调试过程中所遇到的问题及解决方法;
(2)算法的时空分析;
(3)经验与体会。

5、用户使用说明:说明如何使用你的程序,详细列出每一步操作步骤。

6、测试结果:列出对于给定的输入所产生的输出结果。

(完整版)C++二叉树基本操作实验报告

(完整版)C++二叉树基本操作实验报告

一、实验目的选择二叉链式存储结构作为二叉树的存储结构,设计一个程序实现二叉树的基本操作(包括建立、输出、前序遍历、中序遍历、后序遍历、求树高、统计叶子总数等)二、实验开发环境Windows 8.1 中文版Microsoft Visual Studio 6.0三、实验内容程序的菜单功能项如下:1------建立一棵二叉树2------前序遍历递归算法3------前序遍历非递归算法4------中序遍历递归算法5------中序遍历非递归算法6------后序遍历递归算法7------后序遍历非递归算法8------求树高9------求叶子总数10-----输出二叉树11-----退出四、实验分析1、建立一棵二叉树2、输入二叉树各节点数据cout<<"请按正确顺序输入二叉树的数据:";cin.getline(t,1000); //先把输入的数据输入到一个t数组3、递归前序遍历void BL1(ECS_data *t){if(NULL!=t){cout<<t->data<<",";BL1(t->l);BL1(t->r);}}4、非递归前序遍历void preOrder2(ECS_data *t){stack<ECS_data*> s;ECS_data *p=t;while(p!=NULL||!s.empty()){while(p!=NULL){cout<<p->data<<" ";s.push(p);p=p->l;}if(!s.empty()){p=s.top();s.pop();p=p->r;}}}5、递归中序遍历void BL2(ECS_data *t){if(NULL!=t){BL2(t->l);cout<<t->data<<",";BL2(t->r);}}6、非递归中序遍历void inOrder2(ECS_data *t) //非递归中序遍历{stack<ECS_data*> s;ECS_data *p=t;while(p!=NULL||!s.empty()){while(p!=NULL){s.push(p);p=p->l;}if(!s.empty()){p=s.top();cout<<p->data<<" ";s.pop();p=p->r;}}}7、递归后序遍历void BL3(ECS_data *t){if(NULL!=t){BL3(t->l);BL3(t->r);cout<<t->data<<",";}}8、非递归后序遍历void postOrder3(ECS_data *t){stack<ECS_data*> s;ECS_data *cur; //当前结点ECS_data *pre=NULL; //前一次访问的结点s.push(t);while(!s.empty()){cur=s.top();if((cur->l==NULL&&cur->r==NULL)||(pre!=NULL&&(pre==cur->l||pre==cur->r))){cout<<cur->data<<" "; //如果当前结点没有孩子结点或者孩子节点都已被访问过s.pop();pre=cur;}else{if(cur->r!=NULL)s.push(cur->r);if(cur->l!=NULL)s.push(cur->l);}}}9、求树高int Height (ECS_data *t){if(t==NULL) return 0;else{int m = Height ( t->l );int n = Height(t->r);return (m > n) ? (m+1) : (n+1);}}10、求叶子总数int CountLeaf(ECS_data *t){static int LeafNum=0;//叶子初始数目为0,使用静态变量if(t)//树非空{if(t->l==NULL&&t->r==NULL)//为叶子结点LeafNum++;//叶子数目加1else//不为叶子结点{CountLeaf(t->l);//递归统计左子树叶子数目CountLeaf(t->r);//递归统计右子树叶子数目}}return LeafNum;}五、运行结果附:完整程序源代码://二叉树链式存储的实现#include<iostream>#include<cstring>#include <stack>using namespace std;struct ECS_data //先定义好一个数据的结构{char data;ECS_data *l;ECS_data *r;};class ECS{private://int level; //树高int n; //表示有多少个节点数int n1; //表示的是数组的总长度值,(包括#),因为后面要进行删除判断ECS_data *temp[1000];public:ECS_data *root;ECS() //初始化{ECS_data *p;char t[1000];int i;int front=0,rear=1; //front表示有多少个节点,rear表示当前插入的点的父母cout<<"请按正确顺序输入二叉树的数据:";cin.getline(t,1000); //先把输入的数据输入到一个t数组//cout<<t<<" "<<endl;int n1=strlen(t); //测量数据的长度n=0;for(i=0;i<n1;i++){if(t[i]!='#'){p=NULL;if(t[i]!=',') //满足条件并开辟内存{n++;p=new ECS_data;p->data=t[i];p->l=NULL;p->r=NULL;}front++;temp[front]=p;if(1 == front){root=p;}else{if((p!=NULL)&&(0==front%2)){temp[rear]->l=p;//刚开始把这里写成了==}if((p!=NULL)&&(1==front%2)){temp[rear]->r=p;}if(1==front%2)rear++; //就当前的数据找这个数据的父母}}}}~ECS() //释放内存{int i;for(i=1;i<=n;i++)if(temp[i]!=NULL)delete temp[i];}void JS() //记录节点的个数{int s;s=n;cout<<"该二叉树的节点数为:"<<s<<endl;}void BL1(ECS_data *t)//递归前序遍历{if(NULL!=t){cout<<t->data<<",";BL1(t->l);BL1(t->r);}}void preOrder2(ECS_data *t) //非递归前序遍历{stack<ECS_data*> s;ECS_data *p=t;while(p!=NULL||!s.empty()){while(p!=NULL){cout<<p->data<<" ";s.push(p);p=p->l;}if(!s.empty()){p=s.top();s.pop();p=p->r;}}}void BL2(ECS_data *t)//递归中序遍历{if(NULL!=t){BL2(t->l);cout<<t->data<<",";BL2(t->r);}}void inOrder2(ECS_data *t) //非递归中序遍历{stack<ECS_data*> s;ECS_data *p=t;while(p!=NULL||!s.empty()){while(p!=NULL){s.push(p);p=p->l;}if(!s.empty()){p=s.top();cout<<p->data<<" ";s.pop();p=p->r;}}}void BL3(ECS_data *t)//递归后序遍历{if(NULL!=t){BL3(t->l);BL3(t->r);cout<<t->data<<",";}}void postOrder3(ECS_data *t) //非递归后序遍历{stack<ECS_data*> s;ECS_data *cur; //当前结点ECS_data *pre=NULL; //前一次访问的结点s.push(t);while(!s.empty()){cur=s.top();if((cur->l==NULL&&cur->r==NULL)||(pre!=NULL&&(pre==cur->l||pre==cur->r))){cout<<cur->data<<" "; //如果当前结点没有孩子结点或者孩子节点都已被访问过s.pop();pre=cur;}else{if(cur->r!=NULL)s.push(cur->r);if(cur->l!=NULL)s.push(cur->l);}}}int Height (ECS_data *t) //求树高{if(t==NULL) return 0;else{int m = Height ( t->l );int n = Height(t->r);return (m > n) ? (m+1) : (n+1);}}int CountLeaf(ECS_data *t) //求叶子总数{static int LeafNum=0;//叶子初始数目为0,使用静态变量if(t)//树非空{if(t->l==NULL&&t->r==NULL)//为叶子结点LeafNum++;//叶子数目加1else//不为叶子结点{CountLeaf(t->l);//递归统计左子树叶子数目CountLeaf(t->r);//递归统计右子树叶子数目}}return LeafNum;}};int main(){ECS a;a.JS();cout<<"递归前序遍历:";a.BL1(a.root);cout<<endl;cout<<"非递归前序遍历:";a.preOrder2(a.root);cout<<endl;cout<<"递归中序遍历:";a.BL2(a.root);cout<<endl;cout<<"非递归中序遍历:";a.inOrder2(a.root);cout<<endl;cout<<"递归后序遍历:";a.BL3(a.root);cout<<endl;cout<<"非递归后序遍历:";a.postOrder3(a.root);cout<<endl;cout<<"树高为:"<<a.Height(a.root)<<endl;cout<<"叶子总数为:"<<a.CountLeaf(a.root)<<endl;return 0;}。

二叉树的顺序存储及基本操作

二叉树的顺序存储及基本操作

二叉树的顺序存储及基本操作二叉树的顺序存储是将树中的节点按照完全二叉树从上到下、从左到右的顺序依次存储到一个一维数组中,采用这种方式存储的二叉树也被称为完全二叉树。

一、在使用顺序存储方式时,可以使用以下公式来计算一个节点的左右子节点和父节点:
1. 左子节点:2i+1(i为父节点的在数组中的下标)
2. 右子节点:2i+2
3. 父节点:(i-1)/2(i为子节点在数组中的下标)
二、基本操作:
1. 创建二叉树:按照上述公式将节点存储到数组中。

2. 遍历二叉树:可采用递归或非递归方式,进行前序、中序、后序、层次遍历。

3. 插入节点:先将节点插入到数组末尾,然后通过比较节点和其父节点的大小,进行上浮操作直到满足二叉树的性质。

4. 删除节点:先将待删除节点和最后一个节点交换位置,然后通过比较交换后的节点和其父节点的大小,进行下沉操作直到满足二
叉树的性质。

5. 查找节点:根据节点值进行查找,可采用递归或非递归方式。

6. 修改节点:根据节点值进行查找,然后进行修改操作。

二叉树的基本操作实验报告

二叉树的基本操作实验报告

二叉树的基本操作实验报告学号姓名实验日期 2012-12-26实验室计算机软件技术实验指导教师设备编号 401实验内容二叉树的基本操作一实验题目实现二叉树的基本操作的代码实现二实验目的1、掌握二叉树的基本特性2、掌握二叉树的先序、中序、后序的递归遍历算法3、通过求二叉树的深度、度为2的结点数和叶子结点数等算法三实习要求(1)认真阅读书上给出的算法(2)编写程序并独立调试四、给出二叉树的抽象数据类型ADT BinaryTree{//数据对象D:D是具有相同特性的数据元素的集合。

//数据关系R:// 若D=Φ,则R=Φ,称BinaryTree为空二叉树;// 若D?Φ,则R={H},H是如下二元关系;// (1)在D中存在惟一的称为根的数据元素root,它在关系H下无前驱; // (2)若D-{root}?Φ,则存在D-{root}={D1,Dr},且D1?Dr =Φ; // (3)若D1?Φ,则D1中存在惟一的元素x1,<root,x1>?H,且存在D1上的关系H1 ?H;若Dr?Φ,则Dr中存在惟一的元素xr,<root,xr>?H,且存在上的关系Hr ?H;H={<root,x1>,<root,xr>,H1,Hr};// (4)(D1,{H1})是一棵符合本定义的二叉树,称为根的左子树;(Dr,{Hr})是一棵符合本定义的二叉树,称为根的右子树。

//基本操作:CreateBiTree( &T, definition ) // 初始条件:definition给出二叉树T的定义。

// 操作结果:按definiton构造二叉树T。

BiTreeDepth( T )// 初始条件:二叉树T存在。

// 操作结果:返回T的深度。

PreOrderTraverse( T, visit() ) // 初始条件:二叉树T存在,Visit是对结点操作的应用函数。

数据结构与算法实验——二叉树基本操作

数据结构与算法实验——二叉树基本操作

二叉树基本操作实验报告实验名称二叉树基本操作实验目的1.熟悉二叉树结点的结构和二叉树的基本操作;2.掌握二叉树每种操作的具体实现;3.学会利用递归方法编写对二叉树这种递归数据结构进行处理的算法;4.在二叉树基本操作的基础上掌握对二叉树的一些其它操作的具体实现方法;5.掌握构造哈夫曼树以及哈夫曼编码的方法。

实验内容编制一个演示二叉树创建、遍历、计算等操作的程序。

问题描述用数据结构相关知识,实现二叉树的定义和操作。

该程序包括二叉树结构类型以及对二叉树操作的具体的函数定义(包括:初始化二叉树、清空二叉树、检查二叉树是否为空、遍历二叉树(先序、后序、中序、层次)、求二叉树的深度、求二叉树所有节点数)。

问题分析该实验是基于C语言和数据结构知识基础的对二叉树的基本操作的检验,无需设计复杂的算法,程序语句也相对简单。

因此,我直接按要求定义了对二叉树操作的具体函数,并于主函数中实现对应的功能调用,其中,功能选择靠switch语句实现。

实验步骤1.需求分析本演示程序用VC++编写,完成二叉树的生成、遍历、计算等基本操作。

①输入的形式和输入值的范围:以字符(其中‘#’表示虚节点)的形式输入,以创建二叉树;在输入二叉树节点前,必须先确定该序列能正确创建二叉树。

②输出的形式:在所有三种操作中都显示操作是否正确以及操作后二叉树的内容。

③程序所能达到的功能:完成二叉树的生成、遍历(包括先序、后序、中序、层次四种方式)、计算等基本操作。

④测试数据:创建操作中依次输入a,b,d,#,g,#,#,#,c,e,#,#,f,#,#生成一个二叉树。

2.概要设计1)为了实现上述程序功能,需要定义二叉树的抽象数据类型:ADT BitTree {数据对象:由一个根节点和两个互不相交的左右子树构成数据关系:结点具有相同的数据类型及层次结构基本操作:Void BinTreeInit(BitTree *T)初始条件:无操作结果:初始化一棵二叉树Void BinTreeCreat(BitTree *T)初始条件:二叉树T已存在操作结果:按先序次序创建一棵二叉树2)本程序包含7个函数:①主函数main() ②初始化二叉树函数BinTreeInit() ③建立一棵二叉树函数BinTreeCreat() ④先序遍历函数PreOrderTraverse() ⑤中序遍历函数InOrderTraverse()⑥后序遍历函数PostOrderTraverse()⑦层次遍历函数LevelOrderTraverse()⑧求二叉树深度函数Countlevel()⑨检验空树函数BinTreeEmpty()⑩求节点数函数 Countnode()函数说明#include<stdio.h>#include<stdlib.h>typedef char Datatype;typedef struct NodeType{Datatype data;struct NodeType *lchild;struct NodeType *rchild;}BiTNode;typedef BiTNode * BinTree;//初始化二叉树。

数据结构二叉树实验报告

数据结构二叉树实验报告二叉树是一种常用的数据结构,它在计算机科学中有着广泛的应用。

本文将介绍二叉树的定义、基本操作以及一些常见的应用场景。

一、二叉树的定义和基本操作二叉树是一种特殊的树形结构,它的每个节点最多有两个子节点。

一个节点的左子节点称为左子树,右子节点称为右子树。

二叉树的示意图如下:```A/ \B C/ \D E```在二叉树中,每个节点可以有零个、一个或两个子节点。

如果一个节点没有子节点,我们称之为叶子节点。

在上面的示例中,节点 D 和 E 是叶子节点。

二叉树的基本操作包括插入节点、删除节点、查找节点和遍历节点。

插入节点操作可以将一个新节点插入到二叉树中的合适位置。

删除节点操作可以将一个指定的节点从二叉树中删除。

查找节点操作可以在二叉树中查找指定的节点。

遍历节点操作可以按照一定的顺序遍历二叉树中的所有节点。

二、二叉树的应用场景二叉树在计算机科学中有着广泛的应用。

下面将介绍一些常见的应用场景。

1. 二叉搜索树二叉搜索树是一种特殊的二叉树,它的每个节点的值都大于其左子树中的节点的值,小于其右子树中的节点的值。

二叉搜索树可以用来实现快速的查找、插入和删除操作。

它在数据库索引、字典等场景中有着重要的应用。

2. 堆堆是一种特殊的二叉树,它的每个节点的值都大于或小于其子节点的值。

堆可以用来实现优先队列,它在任务调度、操作系统中的内存管理等场景中有着重要的应用。

3. 表达式树表达式树是一种用来表示数学表达式的二叉树。

在表达式树中,每个节点可以是操作符或操作数。

表达式树可以用来实现数学表达式的计算,它在编译器、计算器等场景中有着重要的应用。

4. 平衡二叉树平衡二叉树是一种特殊的二叉树,它的左子树和右子树的高度差不超过1。

平衡二叉树可以用来实现高效的查找、插入和删除操作。

它在数据库索引、自平衡搜索树等场景中有着重要的应用。

三、总结二叉树是一种常用的数据结构,它在计算机科学中有着广泛的应用。

本文介绍了二叉树的定义、基本操作以及一些常见的应用场景。

二叉树的基本操作与实现实验报告

二叉树的基本操作与实现实验报告二叉树是一种重要的数据结构,在计算机科学领域中被广泛应用。

本实验将介绍二叉树的基本操作与实现,并给出相应的实验报告。

一、引言二叉树是一种特殊的树状结构,每个节点至多有两个子节点。

二叉树有许多重要的特性,如平衡二叉树、二叉树等,应用广泛。

在本实验中,我们将介绍二叉树的基本操作和实现。

二、实验目的1.掌握二叉树的基本概念和特性;2.熟悉二叉树的基本操作,包括创建、插入、删除、遍历等;3.学会使用编程语言实现二叉树的基本操作。

三、实验内容本实验主要包括以下内容:1.二叉树的定义和基本概念;2.二叉树的基本操作,包括创建、插入、删除、遍历等;3.使用编程语言实现二叉树的基本操作;4.测试和验证二叉树的基本操作的正确性。

四、实验步骤1.二叉树的定义和基本概念二叉树是一种树状结构,每个节点至多有两个子节点。

二叉树的每个节点包含一个数据项和指向左子树和右子树的指针。

二叉树的特性有很多,如完全二叉树、平衡二叉树、二叉树等。

2.二叉树的基本操作(1)创建二叉树:可以通过手动输入节点数据来创建二叉树,也可以通过读取文件中的数据来创建二叉树。

(2)插入节点:在指定位置插入一个新节点。

(3)删除节点:删除指定位置的节点。

(4)遍历二叉树:有前序遍历、中序遍历和后序遍历三种遍历方式。

3.使用编程语言实现二叉树的基本操作实现二叉树的基本操作可以使用编程语言来完成。

我们可以定义一个二叉树的结构体,包含节点数据和指向左右子树的指针。

然后根据具体的需求,实现相应的操作函数。

4.测试和验证二叉树的基本操作的正确性在完成二叉树的基本操作后,我们可以编写测试代码来验证操作的正确性。

通过创建二叉树,并进行插入、删除和遍历操作,观察输出结果是否符合预期。

五、实验结果与分析在完成二叉树的基本操作后,我们可以进行测试和验证。

通过输出二叉树的遍历结果,比对预期结果来判断操作是否正确。

同时,我们还可以观察二叉树的结构和特性,如是否满足平衡二叉树或二叉树的条件。

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

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)//存在左子树,将左子树根节点入队列

二叉树的基本操作

二叉树的基本操作二叉树是一种常见的数据结构,它由节点组成,每个节点最多连接两个子节点,分别称为左子节点和右子节点。

二叉树的基本操作包括创建、插入、删除、查找和遍历,下面将对这些操作进行详细介绍。

一、创建二叉树创建二叉树的方法有多种,其中最常用的是使用递归的方式。

递归创建二叉树时,可以先创建根节点,然后递归创建左子树和右子树。

如果子树为空,则使用特殊字符表示。

二、插入节点插入节点是向二叉树中添加新节点的操作。

插入节点的位置通常由二叉树的特性决定,左子节点小于父节点,右子节点大于父节点。

插入节点时,需要先找到插入位置,然后创建新节点,并将其连接到对应的位置。

三、删除节点删除节点是从二叉树中移除指定节点的操作。

删除节点的方式取决于节点的位置和子节点的情况。

如果要删除的节点是叶子节点,则直接将其删除即可。

如果要删除的节点有一个子节点,则将其子节点连接到父节点。

如果要删除的节点有两个子节点,则需要找到替代节点,将替代节点的值复制到当前位置,并将替代节点删除。

四、查找节点查找节点是在二叉树中寻找特定节点的操作。

常用的方式有深度优先(DFS)和广度优先(BFS)。

深度优先通常使用递归实现,分为前序遍历、中序遍历和后序遍历三种方式。

广度优先通常使用队列实现,先访问根节点,然后访问其所有子节点,再逐层访问下去,直到找到目标节点或遍历完整棵树。

五、遍历二叉树遍历二叉树是指按照一定顺序访问二叉树中的所有节点,常用的方式有前序遍历、中序遍历和后序遍历。

前序遍历先访问根节点,然后递归遍历左子树和右子树;中序遍历先递归遍历左子树,然后访问根节点,再遍历右子树;后序遍历先递归遍历左子树和右子树,然后访问根节点。

以上是二叉树的基本操作,通过这些操作可以有效地管理和处理二叉树数据结构。

在实际应用中,二叉树常用于、排序和表达等方面,因为它具有较高的查询效率和灵活性。

对于使用二叉树的相关算法和数据结构,理解和掌握其基本操作是非常重要的。

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

实验四二叉树基本操作(4课时)一、实验目的1.掌握二叉树的结构特征,以及各种存储结构的特点及使用范围。

2.掌握用指针类型描述、访问和处理二叉树的运算。

二、实验要求1.设计子函数实现题目要求的功能;2.编译、连接通过,熟练使用命令键;3.运行结果正确,输入输出有提示,格式美观。

三、实验设备、材料和工具1.奔腾2计算机或以上机型2.turboc2,win-tc四、实验内容和步骤实验内容:1.先序输出二叉树的所有结点。

2.求二叉树高度。

3.哈夫曼树及其编码。

五、实验报告要求1.针对程序的健壮性准备好测试数据;2.结果分析中如实填写运行后的结果,并画出二叉树。

六、根据实验过程填写下面内容1.程序及结果:# include <stdio.h>#include <malloc.h>#include <conio.h>#itypedef char DataType;typedef struct Node{DataType data;struct Node *LChild;struct Node *RChild;}BiTNode, *BiTree;void CreateBiTree(BiTree *bt){char ch;ch = getchar();if(ch=='.') *bt=NULL;else{*bt=(BiTree)malloc(sizeof(BiTNode)); //生成一个新结点(*bt)->data=ch;CreateBiTree(&((*bt)->LChild)); //生成左子树CreateBiTree(&((*bt)->RChild)); //生成右子树}}#include "bitree.h"void PreOrder(BiTree root)/*先序遍历二叉树, root为指向二叉树根结点的指针*/{if (root!=NULL){printf("%c ",root ->data); /*输出结点*/PreOrder(root ->LChild); /*先序遍历左子树*/PreOrder(root ->RChild); /*先序遍历右子树*/ }}void main(){BiTree T;printf("按扩展先序遍历序列建立二叉树,请输入序列:\n");CreateBiTree(&T);printf("先序遍历输出序列为:");PreOrder(T);getch();}#include <stdio.h>#include <malloc.h>#include <conio.h>typedef int DataType;typedef struct NodeDataType data;struct Node *LChild;struct Node *RChild;}BiTNode, *BiTree;void CreateBiTree(BiTree *bt){int ch;ch = getint();if(ch=='-1') *bt=NULL;else{*bt=(BiTree)malloc(sizeof(BiTNode)); //生成一个新结点(*bt)->data=ch;CreateBiTree(&((*bt)->LChild)); //生成左子树CreateBiTree(&((*bt)->RChild)); //生成右子树}}#include "bitree.h"void PreOrder(BiTree root)/*先序遍历二叉树, root为指向二叉树根结点的指针*/{if (root!=NULL){printf("%d ",root ->data); /*输出结点*/PreOrder(root ->LChild); /*先序遍历左子树*/PreOrder(root ->RChild); /*先序遍历右子树*/ }}void main(){BiTree T;printf("按扩展先序遍历序列建立二叉树,请输入序列:\n");CreateBiTree(&T);printf("先序遍历输出序列为:");PreOrder(T);getch();}2.程序#include "bitree.h"int PostTreeDepth(BiTree bt) /* 后序遍历求二叉树的高度递归算法*/ {int hl,hr,max;if(bt!=NULL){hl=PostTreeDepth(bt->LChild); /* 求左子树的深度*/hr=PostTreeDepth(bt->RChild); /* 求右子树的深度*/max=hl>hr?hl:hr; /* 得到左、右子树深度较大者*/return(max+1); /* 返回树的深度*/ }else return(0); /* 如果是空树,则返回0 */}void main(){BiTree T;int h;printf("按扩展先序遍历序列建立二叉树,请输入序列:\n");CreateBiTree(&T);h = PostTreeDepth(T);printf("The depth of this tree is:%d\n",h);getch();}结果:3.程序及结果:#include <stdio.h>#include <stdlib.h>#include <string.h>typedef char* HuffmanCode;/*动态分配数组,存储哈夫曼编码*/typedef struct{unsigned int weight ; /* 用来存放各个结点的权值*/unsigned int parent, LChild,RChild ; /*指向双亲、孩子结点的指针*/ }HTNode, * HuffmanTree; /*动态分配数组,存储哈夫曼树*/void select(HuffmanTree *ht,int n, int *s1, int *s2){int i;int min;for(i=1; i<=n; i++){if((*ht)[i].parent == 0){min = i;i = n+1;}}for(i=1; i<=n; i++){if((*ht)[i].parent == 0){if((*ht)[i].weight < (*ht)[min].weight)min = i;}}*s1 = min;for(i=1; i<=n; i++){if((*ht)[i].parent == 0 && i!=(*s1)){min = i;i = n+1;}}for(i=1; i<=n; i++){if((*ht)[i].parent == 0 && i!=(*s1)){if((*ht)[i].weight < (*ht)[min].weight)min = i;}}*s2 = min;}void CrtHuffmanTree(HuffmanTree *ht , int *w, int n){ /* w存放已知的n个权值,构造哈夫曼树ht */int m,i;int s1,s2;m=2*n-1;*ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); /*0号单元未使用*/for(i=1;i<=n;i++){/*1-n号放叶子结点,初始化*/(*ht)[i].weight = w[i];(*ht)[i].LChild = 0;(*ht)[i].parent = 0;(*ht)[i].RChild = 0;}for(i=n+1;i<=m;i++){(*ht)[i].weight = 0;(*ht)[i].LChild = 0;(*ht)[i].parent = 0;(*ht)[i].RChild = 0;} /*非叶子结点初始化*//* ------------初始化完毕!对应算法步骤1---------*/for(i=n+1;i<=m;i++) /*创建非叶子结点,建哈夫曼树*/{ /*在(*ht)[1]~(*ht)[i-1]的范围内选择两个parent为0且weight最小的结点,其序号分别赋值给s1、s2返回*/select(ht,i-1,&s1,&s2);(*ht)[s1].parent=i;(*ht)[s2].parent=i;(*ht)[i].LChild=s1;(*ht)[i].RChild=s2;(*ht)[i].weight=(*ht)[s1].weight+(*ht)[s2].weight;}}/*哈夫曼树建立完毕*/void outputHuffman(HuffmanTree HT, int m){if(m!=0){printf("%d ", HT[m].weight);outputHuffman(HT,HT[m].LChild);outputHuffman(HT,HT[m].RChild);}}void CrtHuffmanCode(HuffmanTree *ht, HuffmanCode *hc, int n)/*从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码*/{char *cd;int i;unsigned int c;int start;int p;hc=(HuffmanCode *)malloc((n+1)*sizeof(char *)); /*分配n个编码的头指针*/cd=(char * )malloc(n * sizeof(char )); /*分配求当前编码的工作空间*/cd[n-1]='\0'; /*从右向左逐位存放编码,首先存放编码结束符*/for(i=1;i<=n;i++) /*求n个叶子结点对应的哈夫曼编码*/{start=n-1; /*初始化编码起始指针*/for(c=i,p=(*ht)[i].parent; p!=0; c=p,p=(*ht)[p].parent) /*从叶子到根结点求编码*/ if( (*ht)[p].LChild == c)cd[--start]='0'; /*左分支标0*/elsecd[--start]='1'; /*右分支标1*/hc[i]=(char *)malloc((n-start)*sizeof(char)); /*为第i个编码分配空间*/strcpy(hc[i],&cd[start]);}free(cd);for(i=1;i<=n;i++)printf("%d编码为%s\n",(*ht)[i].weight,hc[i]);}void main(){HuffmanTree HT;HuffmanCode HC;int *w;int i,n; // the number of elements;int wei; // the weight of a element;int m;printf("input the total number of the Huffman Tree:" );scanf("%d",&n);w=(int *)malloc((n+1)*sizeof(int));for(i=1;i<=n;i++){printf("input the %d element's weight:",i);fflush(stdin);scanf("%d",&wei);w[i]=wei;}CrtHuffmanTree(&HT,w,n);m = 2*n-1;outputHuffman(HT,m);printf("\n");CrtHuffmanCode(&HT,&HC,n); }。

相关文档
最新文档