实验四 树和二叉树及其应用(I)

合集下载

二叉树实验报告

二叉树实验报告

二叉树实验报告二叉树实验报告引言:二叉树作为一种常用的数据结构,在计算机科学领域中具有广泛的应用。

本实验旨在通过实际操作和观察,深入理解二叉树的特性和运用。

一、二叉树的基本概念1.1 二叉树的定义二叉树是一种特殊的树形结构,每个节点最多有两个子节点,分别称为左子节点和右子节点。

树的最顶层节点称为根节点。

1.2 二叉树的特点二叉树具有以下特点:- 每个节点最多有两个子节点,分别称为左子节点和右子节点;- 左子节点的值小于等于父节点的值,右子节点的值大于等于父节点的值;- 二叉树的左子树和右子树也是二叉树。

二、二叉树的遍历方式2.1 先序遍历先序遍历是指先访问根节点,然后按照先序遍历的方式依次访问左子树和右子树。

2.2 中序遍历中序遍历是指按照中序遍历的方式依次访问左子树,根节点和右子树。

2.3 后序遍历后序遍历是指按照后序遍历的方式依次访问左子树,右子树和根节点。

三、二叉树的实验操作3.1 二叉树的创建为了便于实验操作,我们选择使用Python编程语言来实现二叉树的创建和操作。

首先,我们需要定义一个二叉树节点的类,包含节点的值、左子节点和右子节点。

3.2 二叉树的插入在已有的二叉树中插入一个新的节点,需要遵循二叉树的规则。

如果插入的节点值小于当前节点的值,则将节点插入到当前节点的左子树;如果插入的节点值大于当前节点的值,则将节点插入到当前节点的右子树。

3.3 二叉树的查找在二叉树中查找一个特定的节点,需要遍历整个二叉树。

从根节点开始,如果要查找的节点值小于当前节点的值,则继续在左子树中查找;如果要查找的节点值大于当前节点的值,则继续在右子树中查找;如果要查找的节点值等于当前节点的值,则找到了目标节点。

3.4 二叉树的删除在二叉树中删除一个节点,需要考虑多种情况。

如果要删除的节点没有子节点,直接将其删除即可;如果要删除的节点只有一个子节点,将子节点替换为要删除的节点;如果要删除的节点有两个子节点,需要找到其右子树中的最小节点,将其值替换到要删除的节点,然后删除最小节点。

实验四 树和二叉树及其应用(I)

实验四 树和二叉树及其应用(I)

姓名学号序#include"DataStructure_BinaryTree.h"//数据结构第六章树与二叉树函数的定义及声明using namespace std;int main(void){system("title 数据结构实验实验四:树和二叉树及其应用(I) "); //设置cmd窗口标题 system("color F1"); //设置控制台窗口的背景色和前景色system("date /T"); //输出当前的日期print();cout << "实验内容一:树的遍历" << endl;BiTree T;int num = 0;cout << " 二叉树的建立:" << endl;cout << " 输入二叉树数据:";GreateBiTree(T); //先序建立二叉树cout << " 二叉树的遍历" << endl << " 【递归遍历】 ";cout << endl << "> 先序遍历:";PreOrderTraverse(T, PrintElement); //先序遍历二叉树cout << endl << "> 中序遍历:";InOrderTraverse(T, PrintElement); //中序遍历二叉树cout << endl << "> 后序遍历:";PostOrderTraverse(T, PrintElement); //后序遍历二叉树cout << endl << "> 层序遍历:" << endl;LevelOrderTraverse(T, PrintElement); //层序遍历二叉树cout << endl<< " 【非递归遍历】";cout << endl << "> 先序遍历:";PreOrderTraverseNonRec(T, PrintElement); //先序遍历二叉树cout << endl << "> 中序遍历:";InOrderTraverseNonRec(T, PrintElement); //中序遍历二叉树cout << endl << "> 后序遍历:";PostOrderTraverseNonRec(T, PrintElement); //后序遍历二叉树cout << endl << "> 层序遍历:";LevelOrderTraverseNonRec(T, PrintElement);//层序遍历二叉树print();cout << endl << "实验内容二:二叉树的基本操作";cout << endl << "<1> 二叉树的深度:" << BiTDepth(T) << endl;LeafTNodeNum(T, num);cout << "<2> 二叉树中叶子结点的数目:" << num << endl;cout << "<3> 交换左右子树:" << endl;ExchangeBiTree(T);cout << " 交换后的二叉树:" << endl;LevelOrderTraverse(T, PrintElement); //层序遍历二叉树BiTree root;TElemType x;int depth;cout << "<4> 查找指定节点的根子树:" << endl << " 请输入需要查找的根节点:x = ";cin >> x;PreOrderLocate(T, x, root); //先序查找以元素值为x的结点为子树,并以root指向其根子树cout << " 以元素x为根节点的根子树:" << endl;LevelOrderTraverse(root, PrintElement); //层序遍历二叉树ChildBiTreeDepth(T, x, depth);cout << "<5> 查找指定节点的根子树的深度:" << endl << " 以元素x为根节点的根子树的深度:" << depth << endl;cout << "<6> 判断根子树是否为完全二叉树:" << endl;if (CompleteBiTree(root))cout << " 以元素x为根节点的根子树是完全二叉树" << endl;elsecout << " 以元素x为根节点的根子树不是完全二叉树" << endl;DelChildBiTree(T, x);cout << "<7> 删除二叉树:" << endl;cout << " 删除以元素x为根节点的根子树后的二叉树:" << endl;LevelOrderTraverse(T, PrintElement); //层序遍历二叉树if (CompleteBiTree(T))cout << " 删除以元素x为根子树后的二叉树是完全二叉树" << endl;elsecout << " 删除以元素x为根子树后的二叉树不是完全二叉树" << endl;DestoryBiTree(T); //销毁二叉链表TDestoryBiTree(root); //销毁二叉树rootreturn 0;}2.头文件”ADT.h”的部分程序如下:#ifndef ADT_H_#define ADT_H_/* ------二叉树数据类型定义------ */typedef char TElemType; //顺序表中元素的数据类型/* ------二叉树链式结构类型定义------ */typedef struct BiTNode{TElemType data; //二叉树结点数据struct BiTNode *lchild, *rchild; //二叉树结点指针}BiTNode, *BiTree; //二叉树结点类型及结构体指针类型/************************栈和队列*************************//* ------栈数据类型定义------ */typedef BiTree SElemType; //顺序表中元素的数据类型/* ------队列数据类型定义------ */typedef BiTree QElemType; //顺序表中元素的数据类型#endif/* ADT_H_ */3.头文件"DataStructure_StackQueue.h"中部分函数定义如下:#include<stdio.h>#include<malloc.h>#include"ADT.h"#include"DataStructure_StackQueue.h" //数据结构第三章栈和队列相关函数的定义及声明/************************************************************* 功能函数声明区************************************************************/Status GreateBiTree(BiTree &T); //按先序输入二叉树中节点的值,'#'字符表示空树,构造二叉链表树TStatus PreOrderTraverse(BiTree T, Status(*Visit)(TElemType e)); //先序递归遍历二叉树TStatus InOrderTraverse(BiTree T, Status(*Visit)(TElemType e)); //中序递归遍历二叉树T Status PostOrderTraverse(BiTree T, Status(*Visit)(TElemType e)); //递归后序遍历二叉树TStatus LevelOrderTraverse(BiTree T, Status(*Visit)(TElemType e)); //递归层序遍历二叉树T Status PreOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e)); //先序非递归遍历二叉树TStatus InOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e)); //中序非递归遍历二叉树TStatus PostOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e)); //后序非递归遍历二叉树TStatus LevelOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e));//层序非递归遍历二叉树Tint BiTDepth(BiTree &T); //求二叉树的深度Status TraverseLevel(BiTree root, int level,Status(*Visit)(TElemType e));//遍历以roo为根节点中的level层的所以节点(从左到右),成功返回1,失败返回0Status PreOrderLocate(BiTree &T, TElemType e, BiTree &T1);//先序查找以元素值为e的结点为子树,并以T1指向其根子树Status ChildBiTreeDepth(BiTree &, TElemType , int &); //求以元素值x的节点的根子树的深度Status InitBiTree(BiTree &T); //初始化二叉链表TStatus BiTreeEmpty(BiTree T); //判断二叉树是否为空,若为空则返回TRUE, 否则返回FALSE Status DestoryBiTree(BiTree &T); //销毁二叉树TStatus DelBiTree(BiTree &); //删除二叉链表TStatus DelChildBiTree(BiTree &, TElemType e); //删除以元素值为e的结点为根子树Status CompleteBiTree(BiTree T); //判断二叉树是否为完全二叉树Status ExchangeBiTree(BiTree &T); //先序交换二叉树的左右子树Status LeafTNodeNum(BiTree T, int &num); //求二叉树的叶子结点的个数,叶子结点个数numStatus CopyBiTree(BiTree &T1, BiTree &T2); //复制二叉树Status PrintElement(TElemType e); //二叉树数据元素操作应用函数/************************************************************* 功能函数定义区************************************************************//** 函数原型:Status PrintElement(TElemType e)* 函数功能:二叉树数据元素操作应用函数* 入口参数:TElemType类型的数据* 出口参数:返回函数结果状态*/Status PrintElement(TElemType e){printf("%c ",e);return OK;} //PrintElement/** 函数原型:Status GreateBiTree(BiTree &T)* 函数功能:按先序输入二叉树中结点的值,'#'字符表示空树,构造二叉链表树T* 入口参数:BiTree类型树T* 出口参数:返回函数结果状态*/Status GreateBiTree(BiTree &T){TElemType data;scanf_s("%c", &data);if (data == '#')T = NULL;else{if (!(T = (BiTree)malloc(sizeof(BiTNode))))return OVERFLOW;T->data = data;GreateBiTree(T->lchild);GreateBiTree(T->rchild);}return OK;} //GreateBiTree/** 函数原型:Status PreOrderTraverse(BiTree T, Status(*Visit)(TElemType e))* 函数功能:先序遍历二叉树T的递归算法,对每个数据元素调用函数Visit一次且仅一次* 入口参数:二叉链表T,Visit是对数据元素操作的应用函数* 出口参数:返回函数结果状态*/Status PreOrderTraverse(BiTree T, Status(*Visit)(TElemType e)){if (T) //判断是否为空树{if (Visit(T->data)) //访问根结点if (PreOrderTraverse(T->lchild, Visit)) //先序遍历左子树if (PreOrderTraverse(T->rchild, Visit)) //先序遍历右子树return OK;return ERROR; //访问根结点失败}elsereturn OK; //访问根结点失败,不能返回ERROR,返回OK,保证所有节点都能被访问} // PreOrderTraverse/** 函数原型:Status PreOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e))* 函数功能:先序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit一次且仅一次* 入口参数:二叉链表T,Visit是对数据元素操作的应用函数* 出口参数:返回函数结果状态*/Status PreOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e)){BiTree p;LinkStack S;InitStack_L(S);p = T;while (p || !StackEmpty_L(S)){if (p){if (!Visit(p->data)) //如果根指针不空,访问根结点return ERROR;Push_L(S, p); //根指针域压栈,继续遍历左子树p = p->lchild;}else//根指针已空,本左子树遍历完毕{Pop_L(S, p); //根指针域退栈,继续遍历右子树p = p->rchild;}}return OK;} // PreOrderTraverseNonRec/** 函数原型:Status InOrderTraverse(BiTree T, Status(*Visit)(TElemType e))* 函数功能:中序遍历二叉树T的递归算法,对每个数据元素调用函数Visit一次且仅一次* 入口参数:二叉链表T,Visit是对数据元素操作的应用函数* 出口参数:返回函数结果状态*/Status InOrderTraverse(BiTree T, Status(*Visit)(TElemType e)){if (T) //判断是否为空树{if (InOrderTraverse(T->lchild, Visit)) //中序遍历左子树if (Visit(T->data)) //访问根结点if (InOrderTraverse(T->rchild, Visit)) //中序遍历右子树return OK;return ERROR; //访问失败}elsereturn OK; //访问失败} // InOrderTraverse/** 函数原型:Status InOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e))* 函数功能:中序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit一次且仅一次* 入口参数:二叉链表T,Visit是对数据元素操作的应用函数* 出口参数:返回函数结果状态*/Status InOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e)){BiTree p;LinkStack S;InitStack_L(S);p = T;while (p || !StackEmpty_L(S)){if (p){Push_L(S, p); //根指针进栈,遍历左子树p = p->lchild;}else{Pop_L(S, p); //根指针退栈,访问根结点,遍历右子树if (!Visit(p->data))return ERROR;p = p->rchild;}}return OK;} // InOrderTraverseNonRec/** 函数原型:Status PostOrderTraverse(BiTree T, Status(*Visit)(TElemType e))* 函数功能:后序遍历二叉树T的递归算法,对每个数据元素调用函数Visit一次且仅一次* 入口参数:二叉链表T,Visit是对数据元素操作的应用函数* 出口参数:返回函数结果状态*/Status PostOrderTraverse(BiTree T, Status(*Visit)(TElemType e)){if (T) //判断是否为空树{if (PostOrderTraverse(T->lchild, Visit)) //后序遍历左子树if (PostOrderTraverse(T->rchild, Visit)) //后序遍历右子树if (Visit(T->data)) //访问根结点return OK;return ERROR; //访问失败}elsereturn OK;} // PostOrderTraverse/** 函数原型:Status PostOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e))* 函数功能:后序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit一次且仅一次* 入口参数:二叉链表T,Visit是对数据元素操作的应用函数* 出口参数:返回函数结果状态*/Status PostOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e)){BiTree p, q, last;LinkStack S;q = last = NULL;InitStack_L(S);p = T;while (p || !StackEmpty_L(S)){while (p) //根指针不空,则进栈,遍历左子树{Push_L(S, p);p = p->lchild;}GetTop_L(S, q);if (!q->rchild || q->rchild == last) //根节点能被访问的条件是右子树为空或已被访问过{if (!Visit(q->data))return ERROR;Pop_L(S, last);}elsep = q->rchild;}return OK;} // PostOrderTraverseNonRec/** 函数原型:Status LevelOrderTraverse(BiTree T, Status(*Visit)(TElemType e))* 函数功能:层序遍历二叉树T的递归算法,对每个数据元素调用函数Visit一次且仅一次* 入口参数:二叉链表T,Visit是对数据元素操作的应用函数* 出口参数:返回函数结果状态*/Status LevelOrderTraverse(BiTree T, Status(*Visit)(TElemType e)){if (!T)return ERROR;for (int level = 0;; level++){if (!TraverseLevel(T, level, Visit))break;printf("\n");}return OK;} //LevelOrderTraverse/** 函数原型:Status LevelOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e)) * 函数功能:层序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit一次且仅一次* 入口参数:二叉链表T,Visit是对数据元素操作的应用函数* 出口参数:返回函数结果状态*/Status LevelOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e)){BiTree p;LinkQueue Q;InitQueue_L(Q);if (T)EnQueue_L(Q, T);while (!QueueEmpty_L(Q)){DeQueue_L(Q, p);Visit(p->data);if (p->lchild)EnQueue_L(Q, p->lchild);if (p->rchild)EnQueue_L(Q, p->rchild);}return OK;} // LevelOrderTraverseNonRec/** 函数原型:Status TraverseLevel(BiTree root,int level,Status(*Visit)(TElemType e))* 函数功能:遍历以roo为根节点中的level层的所以节点(从左到右),成功返回1,失败返回0* 入口参数:root:二叉树的根结点,level:层次数,根结点为第0层* 出口参数:返回函数结果状态*/Status TraverseLevel(BiTree root, int level, Status(*Visit)(TElemType e)){if (!root || level < 0)return ERROR;if (level == 0)return Visit(root->data);elsereturn TraverseLevel(root->lchild, level - 1, Visit) + TraverseLevel(root -> rchild, level - 1, Visit);} //PrintBiTreeLevel/** 函数原型:int BiTDepth(BiTree T)* 函数功能:求二叉树的深度* 入口参数:二叉链表T* 出口参数:二叉链表的深度*/int BiTDepth(BiTree &T){int ldepth, rdepth;if (!T)return 0;else{ldepth = BiTDepth(T->lchild) + 1;rdepth = BiTDepth(T->rchild) + 1;return ldepth > rdepth ? ldepth : rdepth;}} //BiTDepth/** 函数原型:Status CompleteBiTree(BiTree T)* 函数功能:判断二叉树是否为完全二叉树* 入口参数:二叉链表T* 出口参数:返回函数结果状态*/Status CompleteBiTree(BiTree T){int d;if (T){d = BiTDepth(T->lchild) - BiTDepth(T->rchild);if (d<0 || d>1)return ERROR;else{if (CompleteBiTree(T->lchild) && CompleteBiTree(T->rchild))return OK;elsereturn ERROR;}}return OK;} //CompleteBiTree/** 函数原型:Status LeafTNodeNum(BiTree T,int &num)* 函数功能:求二叉树的叶子结点的个数,叶子结点个数num* 入口参数:二叉链表T* 出口参数:返回函数结果状态*/Status LeafTNodeNum(BiTree T,int &num){if (!T)return ERROR;else{if (!T->lchild&&!T->rchild)num++;LeafTNodeNum(T->lchild, num);LeafTNodeNum(T->rchild, num);}return OK;} //LeafTNodeNum1、此次实验完成了对二叉树的遍历操作和二叉树的一些基本操作。

数据结构之树和二叉树的应用

数据结构之树和二叉树的应用

第六章树和二叉树的应用6.1二叉排序树和平衡二叉树在实际应用中,常常需要在一组记录中检索一个记录,向其中插入一个记录或者把找到的记录删除。

如果记录无序,查找起来将会很慢。

如果记录有序,查找将会很快。

但是遇到动态增减变化时,需要移动大量的元素。

即使使用链表结构,查找起来也相当麻烦。

非常需要一中插入、删除、和检索记录效率都很高的数据组织方法。

二叉排序(查找、搜索)树就是这样一种高效的数据结构。

二叉排序树也称二叉查找树或二叉搜索树。

它或者是一棵空树;或者有性质:(1)若其左子树不空,则左子树上所有结点的值均小于根结点的值。

(2)若其右子树不空,则右子树上所有结点的值均大于根结点的值。

(3)左右子树也为二叉排序树。

图5.21就是一棵二叉排序树。

二叉排序树通常采用二叉链存储结构。

二叉链存储结构的结点类型定义:typedefstructtnode{KeyTypekey;//关键字域ElemTypedata;//其他数据域structtnode*lchild,*rchild;//指针}BSTNode;中序遍历二叉排序树可以得到有序序列。

6.1.2二叉排序树的基本运算二叉排序树的基本运算如下:1.BSTSearch(bt,k)在二叉排序树bt中,查找值为k的结点。

2.BSTInsert(bt,k)在二叉排序树bt中,插入值为k的结点。

3.CreateBST(bt,str,n)创建二叉排序树4.输出二叉排序树DispBST(bt)5.删除结点BSTDelete(bt,k)1.查找结点BSTSearch(bt,k)方法:将给定值k与查找树的根结点关键码比较。

若相等,查找成功,结束查找过程。

否则,a.当给k小于根结点关键码,查找将在以左子女为根的子树上继续进行;b.当给k大于根结点关键码,查找将在以右子女为根的子树上继续进行;c .若K 等于当前结点的关键字,则返回;如此反复,直至找到或子树为空,查找失败时为止。

例如,查找图5.21中关键字等于45的结点。

数据结构实验四 树与二叉树

数据结构实验四    树与二叉树

数据结构实验四树与二叉树班级学号姓名分数一、实验目的:1、掌握二叉树的定义、性质及存储方式,各种遍历算法。

2、掌握这种存储结构的构造算法以及基于每一种结构上的算法设计3、初步掌握算法分析方法并对已设计出的算法进行分析,给出相应的结果。

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

三、实验内容及分析:1、分析、理解程序。

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

四、程序的调试及运行结果先序遍历中序遍历后序遍历树的深度及叶子树层次遍历五、程序代码#include"stdio.h"#include"stdlib.h"#include"string.h"#define Max 20 //结点的最大个数typedef struct node{char data;struct node *lchild,*rchild;}BinTNode; //自定义二叉树的结点类型typedef BinTNode *BinTree; //定义二叉树的指针int NodeNum,leaf; //NodeNum为结点数,leaf为叶子数//==========基于先序遍历算法创建二叉树==============//=====要求输入先序序列,其中加入虚结点"#"以示空指针的位置========== BinTree CreatBinTree(void){BinTree T;char ch;if((ch=getchar())=='#')return(NULL); //读入#,返回空指针else{T= (BinTNode *)malloc(sizeof(BinTNode)); //生成结点T->data=ch;T->lchild=CreatBinTree(); //构造左子树T->rchild=CreatBinTree(); //构造右子树return(T);}}//========NLR 先序遍历=============void Preorder(BinTree T){if(T) {printf("%c",T->data); //访问结点Preorder(T->lchild); //先序遍历左子树Preorder(T->rchild); //先序遍历右子树}}//========LNR 中序遍历===============void Inorder(BinTree T){if(T) {Inorder(T->lchild); //中序遍历左子树printf("%c",T->data); //访问结点Inorder(T->rchild); //中序遍历右子树}}//==========LRN 后序遍历============void Postorder(BinTree T){if(T) {Postorder(T->lchild); //后序遍历左子树Postorder(T->rchild); //后序遍历右子树printf("%c",T->data); //访问结点}}//=====采用后序遍历求二叉树的深度、结点数及叶子数的递归算法======== int TreeDepth(BinTree T){int hl,hr,max;if(T){hl=TreeDepth(T->lchild); //求左深度hr=TreeDepth(T->rchild); //求右深度max=hl>hr? hl:hr; //取左右深度的最大值NodeNum=NodeNum+1; //求结点数if(hl==0&&hr==0) leaf=leaf+1; //若左右深度为0,即为叶子。

树和二叉树的实验报告

树和二叉树的实验报告

《数据结构》实验报告题目: 树和二叉树一、用二叉树来表示代数表达式(一)需求分析输入一个正确的代数表达式, 包括数字和用字母表示的数, 运算符号+ - * / ^ =及括号。

系统根据输入的表达式建立二叉树, 按照先括号里面的后括号外面的, 先乘后除的原则, 每个节点里放一个数字或一个字母或一个操作符, 括号不放在节点里。

分别先序遍历, 中序遍历, 后序遍历此二叉树, 并输出表达式的前缀式, 中缀式和后缀式。

(二)系统设计1.本程序中用到的所有抽象数据类型的定义;typedef struct BiNode //二叉树的存储类型{char s[20];struct BiNode *lchild,*rchild;}BiTNode,*BiTree;2.主程序的流程以及各程序模块之间的层次调用关系, 函数的调用关系图:3. 列出各个功能模块的主要功能及输入输出参数void push(char cc)初始条件: 输入表达式中的某个符号操作结果: 将输入的字符存入buf数组中去BiTree Create_RTree()初始条件: 给出二叉树的定义表达式操作结果:构造二叉树的右子树, 即存储表达式等号右侧的字符组BiTree Create_RootTree()初始条件: 给出二叉树的定义表达式操作结果:构造存储输入表达式的二叉树, 其中左子树存储‘X’, 根节点存储‘:=’void PreOrderTraverse(BiTree T)初始条件: 二叉树T存在操作结果:先序遍历T, 对每个节点调用函数Visit一次且仅一次void InOrderTraverse(BiTree T)初始条件: 二叉树T存在操作结果:中序遍历T, 对每个节点调用函数Visit一次且仅一次void PostOrderTraverse(BiTree T)初始条件: 二叉树T存在操作结果:后序遍历T, 对每个节点调用函数Visit一次且仅一次int main()主函数, 调用各方法, 操作成功后返回0(三)调试分析调试过程中还是出现了一些拼写错误, 经检查后都能及时修正。

树和二叉树的实验报告

树和二叉树的实验报告

树和二叉树的实验报告树和二叉树的实验报告一、引言树和二叉树是计算机科学中常用的数据结构,它们在各种算法和应用中都有广泛的应用。

本实验旨在通过实际操作和观察,深入了解树和二叉树的特性和操作。

二、树的构建与遍历1. 树的概念和特性树是一种非线性的数据结构,由节点和边组成。

每个节点可以有零个或多个子节点,其中一个节点没有父节点的称为根节点。

树的特点包括层次结构、唯一根节点和无环等。

2. 树的构建在本实验中,我们使用Python语言构建了一棵树。

通过定义节点类和树类,我们可以方便地创建树的实例,并添加节点和连接节点之间的边。

3. 树的遍历树的遍历是指按照一定顺序访问树中的所有节点。

常见的遍历方式有前序遍历、中序遍历和后序遍历。

我们在实验中实现了这三种遍历方式,并观察了它们的输出结果。

三、二叉树的实现与应用1. 二叉树的概念和特性二叉树是一种特殊的树,每个节点最多有两个子节点,分别称为左子节点和右子节点。

二叉树的特点包括唯一根节点、每个节点最多有两个子节点和子节点的顺序等。

2. 二叉树的实现我们使用Python语言实现了二叉树的数据结构。

通过定义节点类和二叉树类,我们可以创建二叉树的实例,并实现插入节点、删除节点和查找节点等操作。

3. 二叉树的应用二叉树在实际应用中有很多用途。

例如,二叉搜索树可以用于实现快速查找和排序算法。

AVL树和红黑树等平衡二叉树可以用于高效地插入和删除操作。

我们在实验中实现了这些应用,并通过实际操作验证了它们的效果。

四、实验结果与讨论通过实验,我们成功构建了树和二叉树的数据结构,并实现了它们的基本操作。

通过观察和分析实验结果,我们发现树和二叉树在各种算法和应用中的重要性和灵活性。

树和二叉树的特性使得它们适用于解决各种问题,例如搜索、排序、图算法等。

同时,我们也发现了一些问题和挑战,例如树的平衡性和节点的插入和删除操作等。

这些问题需要进一步的研究和优化。

五、总结本实验通过实际操作和观察,深入了解了树和二叉树的特性和操作。

树和二叉树实验报告

树和二叉树实验报告

树和二叉树、实验目的1. 掌握二叉树的结构特征,以及各种存储结构的特点及适用范围。

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

、实验要求1. 认真阅读和掌握本实验的程序。

2. 上机运行本程序。

3. 保存和打印出程序的运行结果,并结合程序进行分析。

4. 按照二叉树的操作需要,重新改写主程序并运行,打印出文件清单和运行结果。

、实验内容1. 输入字符序列,建立二叉链表。

2. 按先序、中序和后序遍历二叉树(递归算法)。

3. 按某种形式输出整棵二叉树。

4. 求二叉树的高度。

5. 求二叉树的叶节点个数。

6. 交换二叉树的左右子树。

7. 借助队列实现二叉树的层次遍历。

8. 在主函数中设计一个简单的菜单,分别调试上述算法。

为了实现对二叉树的有关操作,首先要在计算机中建立所需的二叉树。

建立二叉树有各种不同的方法。

一种方法是利用二叉树的性质5来建立二叉树,输入数据时要将节点的序号(按满二叉树编号)和数据同时给出:(序号,数据元素0)。

另一种方法是主教材中介绍的方法,这是一个递归方法,与先序遍历有点相似。

数据的组织是先序的顺序,但是另有特点,当某结点的某孩子为空时以字符“#”来充当,也要输入。

若当前数据不为“#”则申请一个结点存入当前数据。

递归调用建立函数,建立当前结点的左右子树。

四、解题思路1、先序遍历:O访问根结点,G先序遍历左子树,C3先序遍历右子树2、中序遍历:O中序遍历左子树,C2访问根结点,。

中序遍历右子树3、后序遍历:O后序遍历左子树,C2后序遍历右子树,C3访问根结点4、层次遍历算法:采用一个队列q,先将二叉树根结点入队列,然后退队列,输出该结点;若它有左子树,便将左子树根结点入队列;若它有右子树,便将右子树根结点入队列,直到队列空为止。

因为队列的特点是先进后出,所以能够达到按层次遍历二叉树的目的。

五、程序清单#in clude<stdio.h>#in clude<stdlib.h>#defi ne M 100typedef char Etype; //定义二叉树结点值的类型为字符型typedef struct BiTNode {//树结点结构Etype data;struct BiTNode *lch,*rch;}BiTNode,*BiTree;BiTree que[M];int fron t=0,rear=0;//函数原型声明BiTNode *creat_bt1();BiTNode *creat_bt2();void preorder(BiTNode *p);void ino rder(BiTNode *p);void postorder(BiTNode *p);void enq ueue(BiTree);BiTree delqueue();void levorder(BiTree);int treedepth(BiTree);void prtbtree(BiTree,i nt);void excha nge(BiTree);in t leafco un t(BiTree);void pain tleaf(BiTree);BiTNode *t;int coun t=0;//主函数void mai n() {char ch;int k;do{prin tf("\n\n\n");prin tf("\n=================== 主菜单===================");prin tf("\n\n 1.建立二叉树方法1");prin tf("\n\n 2.建立二叉树方法2");prin tf("\n\n 3•先序递归遍历二叉树”);prin tf("\n\n 4•中序递归遍历二叉树”);prin tf("\n\n 5.后序递归遍历二叉树”);printf("\n\n 6.层次遍历二叉树”);prin tf("\n\n 7.计算二叉树的高度”);prin tf("\n\n 8.计算二叉树中叶结点个数”);prin tf("\n\n 9.交换二叉树的左右子树”);printf("\n\n 10.打印二叉树”);printf("\n\n 0.结束程序运行”);prin tf("\n============================================");printf("\n 请输入您的选择(0,1,2,3,4,5,6,7,8,9,10)");sea nf("%d",&k);switch(k){case 1:t=creat_bt1( );break; //调用性质5建立二叉树算法case 2:pri ntf("\n 请输入二叉树各结点值:");fflush(stdi n);t=creat_bt2();break; //调用递归建立二叉树算法case 3:if(t){printf("先序遍历二叉树:");preorder(t);prin tf("\n");}else printf(” 二叉树为空!\n");break;case 4:if(t){printf("中序遍历二叉树:");ino rder(t);prin tf("\n");}else printf("二叉树为空!\n");break;case 5:if(t)postorder(t);{printf("后序遍历二叉树:");prin tf("\n");}else printf(” 二叉树为空!\n");break;case 6:if(t){printf("层次遍历二叉树:");levorder(t);prin tf("\n");}else printf("二叉树为空!\n");break;case 7:if(t){printf("二叉树的高度为:%d",treedepth(t));prin tf("\n");}else printf("二叉树为空!\n");break;case 8:if(t){printf("二叉树的叶子结点数为:%d\n",leafcount(t));prin tf("\n");printf("二叉树的叶结点为:");pai ntleaf(t);else printf(” 二叉树为空!\n");break;case 9:if(t){printf("交换二叉树的左右子树:\n");excha nge(t);prtbtree(t,0);prin tf("\n");}else printf("二叉树为空!\n");break;case 10:if(t){printf("逆时针旋转90度输出的二叉树:\n");prtbtree(t,0);prin tf("\n");}else printf("二叉树为空!\n");break;case 0:exit(0);} //switch}while(k>=1 &&k<=10);printf("\n再见!按回车键,返回… \n");ch=getchar();} //main//利用二叉树性质5,借助一维数组V建立二叉树BiTNode *creat_bt1(){ BiTNode *t,*p,*v[20];i nt i,j;Etype e;/*输入结点的序号i、结点的数据e*/printf("\n请输入二叉树各结点的编号和对应的值(如1,a):");sca nf("%d,%c",&i,&e);while(i!=0&&e!='#') {//当i为0, e为#时,结束循环p=(BiTNode*)malloc(sizeof(BiTNode));p->data=e;p->lch=NULL;p->rch=NULL;v[i]=p;if(i==1)t=p; //序号为1的结点是根else{j=i/2;if(i%2==0)v[j]->lch=p;//序号为偶数,作为左孩子else v[j]_>rch=p; //序号为奇数,作为右孩子}printf("\n请继续输入二叉树各结点的编号和对应的值:”);scan f("%d,%c",&i, &e);}return(t);}//creat_bt1;//模仿先序递归遍历方法,建立二叉树BiTNode *creat_bt2(){BiTNode *t;Etype e;scan f("%c",&e);if(e==' #')t=NULL; //对于#值,不分配新结点else{t=(BiTNode *)malloc(sizeof(BiTNode));t->data=e;t->lch=creat_bt2(); //左孩子获得新指针值t->rch=creat_bt2(); //右孩子获得新指针值return(t);} 〃creat_bt2//先序递归遍历二叉树void preorder(BiTNode *p) {if(P){prin tf("%3c",p->data);preorder(p_>lch);preorder(p->rch);}} //preorder〃中序递归遍历二叉树void ino rder(BiTNode *p){if(p){ino rder(p->lch);prin tf("%3c",p->data);ino rder(p->rch);}} //ino rder//后序递归遍历二叉树void postorder(BiTNode *p){ if(p){ postorder(p->lch);postorder(p->rch);prin tf("%3c",p->data);}} //postorder void enq ueue(BiTree T){if(fron t!=(rear+1)%M){rear=(rear+1)%M;que[rear]=T;}}BiTree delqueue(){if(fron t==rear)return NULL;fron t=(fro nt+1)%M;return(que[fro nt]);}void levorder(BiTree T)//层次遍历二叉树{BiTree p;if(T){enq ueue(T);while(fro nt!=rear){p=delqueue( );prin tf("%3d",p->data);if(p->lch!=NULL)e nqueue(p->lch); if(p->rch!=NULL)e nq ueue(p->rch);}}} int treedepth(BiTree bt){int hl,hr,max;if(bt!=NULL){ hl=treedepth(bt->lch); hr=treedepth(bt->rch);max=(hl>hr)?hl:hr; return (max+1);}else return (0);} void prtbtree(BiTree bt,i nt level)形{int j;if(bt){prtbtree(bt->rch,level+1);for(j=0;j<=6*level;j++)pri ntf(" ”);prin tf("%c\n",bt->data);prtbtree(bt->lch,level+1);}}//计算二叉树的高度〃逆时针旋转90度输出二叉树树void excha nge(BiTree bt) // 交换二叉树左右子树{BiTree p;if(bt){p=bt->lch;bt->lch=bt->rch;bt->rch=p;excha nge(bt->lch);excha nge(bt->rch);}}in t leafcou nt(BiTree bt) // 计算叶结点数{if(bt!=NULL){leafc oun t(bt->lch);leafc oun t(bt->rch);if((bt->lch==NULL) &&(bt->rch==NULL))coun t++;}return(co unt);void pai ntleaf(BiTree bt) // 输出叶结点{if(bt!=NULL) {if(bt->lch==NULL&&bt->rch==NULL)prin tf("%3c",bt->data);pain tleaf(bt->lch);pain tleaf(bt->rch);}}图11.2所示二叉树的输入数据顺序应该是:abd#g###ce#h##f##图11.2 二叉树示意图运行结果:=================王采单1. 建立二叉树方法12. 建立二叉树方法23•先序递归遍历二叉树4•中序递归遍历二叉树5. 后序递归遍历二叉树6. 层次遍历二叉树7. 计算二叉树的高度8. 计算二叉树中叶结点个数9. 交换二叉树的左右子树10. 打印二叉树0.结束程序运行请输入您的选择(0,1,2,3,4,5,6,7,8,9,10) 1请输入二叉树各结点的编号和对应的值(如1,a):1,a 请继续输入二叉树各结点的编号和对应的值:2,b请继续输入二叉树各结点的编号和对应的值:3,c请继续输入二叉树各结点的编号和对应的值:4,d请继续输入二叉树各结点的编号和对应的值:6,e请继续输入二叉树各结点的编号和对应的值:7,f请继续输入二叉树各结点的编号和对应的值:9,g请继续输入二叉树各结点的编号和对应的值:13,h请继续输入二叉树各结点的编号和对应的值:===================主菜单===================");1. 建立二叉树方法12. 建立二叉树方法23•先序递归遍历二叉树4•中序递归遍历二叉树5. 后序递归遍历二叉树6. 层次遍历二叉树7. 计算二叉树的高度8. 计算二叉树中叶结点个数9. 交换二叉树的左右子树10. 打印二叉树0.结束程序运行请输入您的选择(0,1,2,3,4,5,6,7,8,9,10) 3先序遍历二叉树:abdgcehf===================主菜单===================");1. 建立二叉树方法12. 建立二叉树方法23•先序递归遍历二叉树4•中序递归遍历二叉树5. 后序递归遍历二叉树6. 层次遍历二叉树7. 计算二叉树的高度8. 计算二叉树中叶结点个数9. 交换二叉树的左右子树10. 打印二叉树0.结束程序运行请输入您的选择(0,1,2,3,4,5,6,7,8,9,10) 4中序遍历二叉树:dgbaehcf===================主菜单===================");1. 建立二叉树方法12. 建立二叉树方法23. 先序递归遍历二叉树4. 中序递归遍历二叉树5. 后序递归遍历二叉树6. 层次遍历二叉树7. 计算二叉树的高度8. 计算二叉树中叶结点个数9. 交换二叉树的左右子树10. 打印二叉树0.结束程序运行请输入您的选择(0,1,2,3,4,5,6,7,8,9,10) 5后序遍历二叉树:gdbhefca===================主菜单===================");1. 建立二叉树方法12. 建立二叉树方法23•先序递归遍历二叉树4•中序递归遍历二叉树5. 后序递归遍历二叉树6. 层次遍历二叉树7. 计算二叉树的高度8. 计算二叉树中叶结点个数9. 交换二叉树的左右子树10. 打印二叉树0.结束程序运行请输入您的选择(0,1,2,3,4,5,6,7,8,9,10) 6层次遍历二叉树:97 98 99100101102103104===================主菜单===================");1. 建立二叉树方法12. 建立二叉树方法23•先序递归遍历二叉树4•中序递归遍历二叉树5. 后序递归遍历二叉树6. 层次遍历二叉树7. 计算二叉树的高度8. 计算二叉树中叶结点个数9. 交换二叉树的左右子树10. 打印二叉树0.结束程序运行请输入您的选择(0,1,2,3,4,5,6,7,8,9,10) 7 二叉树的高度为:4王采单 1. 建立二叉树方法 12. 建立二叉树方法 23•先序递归遍历二叉树4•中序递归遍历二叉树5. 后序递归遍历二叉树6. 层次遍历二叉树7. 计算二叉树的高度8. 计算二叉树中叶结点个数9. 交换二叉树的左右子树10. 打印二叉树0.结束程序运行请输入您的选择(0,1,2,3,4,5,6,7,8,9,10) 8 二叉树的叶子结点数为:3二叉树的叶结点为: g h f1. 建立二叉树方法 12. 建立二叉树方法 23. 先序递归遍历二叉树===================王采单"); ”);4•中序递归遍历二叉树5. 后序递归遍历二叉树6. 层次遍历二叉树7. 计算二叉树的高度8. 计算二叉树中叶结点个数9. 交换二叉树的左右子树10. 打印二叉树0.结束程序运行请输入您的选择(0,1,2,3,4,5,6,7,8,9,10) 9交换二叉树的左右子树:dgbaehc===================王采单");1. 建立二叉树方法12. 建立二叉树方法23•先序递归遍历二叉树4•中序递归遍历二叉树5. 后序递归遍历二叉树6. 层次遍历二叉树7. 计算二叉树的高度8. 计算二叉树中叶结点个数9. 交换二叉树的左右子树10. 打印二叉树0.结束程序运行请输入您的选择(0,1,2,3,4,5,6,7,8,9,10) 10 逆时针旋转90度输出的二叉树:dgbaehc王采单”);1. 建立二叉树方法12. 建立二叉树方法23•先序递归遍历二叉树4•中序递归遍历二叉树5. 后序递归遍历二叉树6. 层次遍历二叉树7. 计算二叉树的高度8. 计算二叉树中叶结点个数9. 交换二叉树的左右子树10. 打印二叉树0.结束程序运行请输入您的选择(0,1,2,3,4,5,6,7,8,9,10) 2请输入二叉树各结点值:abd#g###ce#h##f##===================主菜单===================");1. 建立二叉树方法12. 建立二叉树方法23•先序递归遍历二叉树4•中序递归遍历二叉树5. 后序递归遍历二叉树6. 层次遍历二叉树7. 计算二叉树的高度8. 计算二叉树中叶结点个数9. 交换二叉树的左右子树10. 打印二叉树0.结束程序运行请输入您的选择(0,1,2,3,4,5,6,7,8,9,10) 0请按任意键继续•• •六、调试心得及收获建立二叉树有两种方法:一种方法是利用二叉树的性质5来建立二叉树;另一种方法是主教材中介绍的方法,这是一个递归方法,与先序遍历有点相似。

树和二叉树的应用

树和二叉树的应用

【实验题目】树和二叉树的应用【实验内容】哈夫曼编码设计【实验目的】掌握树和二叉树的概念及工作原理,运用其原理及概念完成上述实验题中的内容。

【实验要求】通过程序设计,实现哈弗曼编码的设计。

更好的掌握与理解课堂上老师所讲的概念与原理,通过树和二叉树的方法实现。

【设计原理】可以利用二叉树来设计二进制的前缀编码。

可以从根节点到叶子节点的路径上分支字符组成的字符串作为该叶子节点字符的编码。

如此得到的必为二进制前缀码。

设计电文总长最短的二进制前缀码既为以N种字符出现的频率作权,设计一棵哈夫曼树的问题,由此得到的二进制前缀编码成为哈弗曼编码。

【程序清单及注释说明】#include<stdio.h>#include<conio.h>#include<iostream.h>#include<string.h>#include<stdlib.h>#define MAXVALUE 10000 /*权值最大值*/#define MAXLEAF 30 /*叶子最多个数*/#define MAXNODE MAXLEAF*2-1 /* 结点数的个数*/#define MAXBIT 50 /*编码的最大位数*/typedef struct node /*结点类型定义*/{char letter;int weight;int parent;int lchild;int rchild;}HNodeType;typedef struct /*编码类型定义*/{char letter;int bit[MAXBIT];int start;}HCodeType;typedef struct /*输入符号的类型*/{char s;int num;}lable;void HuffmanTree(HNodeType HuffNode[],int n,lable a[]) /*定义哈弗曼树*/ {int i,j,m1,m2,x1,x2,temp1;char temp2;for (i=0;i<2*n-1;i++) /*结点初始化*/{HuffNode[i].letter=0;HuffNode[i].weight=0;HuffNode[i].parent=-1;HuffNode[i].lchild=-1;HuffNode[i].rchild=-1;}for (i=0;i<n-1;i++)for (j=i+1;j<n-1;j++) /*对输入字符按权值大小进行排序*/if (a[j].num>a[i].num){temp1=a[i].num;a[i].num=a[j].num;a[j].num=temp1;temp2=a[i].s;a[i].s=a[j].s;a[j].s=temp2;}for (i=0;i<n;i++){HuffNode[i].weight=a[i].num;HuffNode[i].letter=a[i].s;}for (i=0;i<n-1;i++) /*构造huffman树*/{m1=m2=MAXV ALUE;x1=x2=0;for (j=0;j<n+i;j++)/*寻找权值最小与次小的结点*/{if (HuffNode[j].parent==-1&&HuffNode[j].weight<m1){m2=m1;x2=x1;m1=HuffNode[j].weight;x1=j;}else if (HuffNode[j].parent==-1&&HuffNode[j].weight<m2){m2=HuffNode[j].weight;x2=j;}}HuffNode[x1].parent=n+i;HuffNode[x2].parent=n+i; /*权值最小与次小的结点进行组合*/HuffNode[n+i].weight=HuffNode[x1].weight+HuffNode[x2].weight;HuffNode[n+i].lchild=x1;HuffNode[n+i].rchild=x2;}}void HuffmanCode(int n,lable a[]){HNodeType HuffNode[MAXNODE];HCodeType HuffCode[MAXLEAF],cd;int i,j,c,p;HuffmanTree(HuffNode,n,a);for (i=0;i<n;i++) /*按结点位置进行编码*/{cd.start=n-1;c=i;p=HuffNode[c].parent;while (p!=-1){if (HuffNode[p].lchild==c)cd.bit[cd.start]=0;else cd.bit[cd.start]=1;cd.start--;c=p;p=HuffNode[c].parent;}for (j=cd.start+1;j<n;j++) /*储存编码*/HuffCode[i].bit[j]=cd.bit[j];HuffCode[i].start=cd.start;}for (i=0;i<n;i++){HuffCode[i].letter=HuffNode[i].letter;printf("%c 哈弗曼编码:",HuffCode[i].letter);for (j=HuffCode[i].start+1;j<n;j++)printf("%d",HuffCode[i].bit[j]);printf("\n");}}int main(){lable data[30];char s[100],*p;int i,count=0;printf("哈夫曼编码设计");printf("\n");printf("输入字符:");scanf("%s",s);for (i=0;i<30;i++){data[i].s=0;data[i].num=0;}p=s;while (*p) /*计算字符个数与出现次数(即权值)*/ {for (i=0;i<=count+1;i++){if (data[i].s==0){data[i].s=*p;data[i].num++;count++;break;}else if (data[i].s==*p){data[i].num++;break;}}p++;}for (i=0;i<count;i++){printf("%c ",data[i].s);printf("权重(出现次数):%d\n",data[i].num);}printf("\n");HuffmanCode(count,data);count=0;return 0;}【运行与测试及结果】【问题及解决方法】进行实验的过程中,刚刚开始的时候定义哈夫曼树出现了错误,程序无法顺利执行,后来经过上网查询,询问老师,查找书籍,将问题顺利的解决了。

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

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

实验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. 什么是二叉树二叉树是一种常见的数据结构,它由节点(Node)组成,在每个节点上有两个子节点,分别称为左子节点(left child)和右子节点(right child)。

二叉树的特点是每个节点最多有两个子节点,且子节点的位置是固定的。

二叉树常用于数据的存储与查找,具有高效的特性。

2. 二叉树的原理2.1 二叉树的节点结构二叉树的节点通常包含三个属性:值(value)、左子节点(left)和右子节点(right)。

struct TreeNode {int val;TreeNode *left;TreeNode *right;};2.2 二叉树的遍历方式•前序遍历(Preorder Traversal):按照根节点 -> 左子树 -> 右子树的顺序进行遍历;•中序遍历(Inorder Traversal):按照左子树 -> 根节点 -> 右子树的顺序进行遍历;•后序遍历(Postorder Traversal):按照左子树 -> 右子树 -> 根节点的顺序进行遍历;•层序遍历(Level Order Traversal):按照层级顺序从上往下,从左到右逐层遍历。

2.3 二叉树的应用二叉树的应用非常广泛,以下是一些常见的应用场景:2.3.1 二叉搜索树(Binary Search Tree,BST)二叉搜索树是一种特殊的二叉树,它满足以下性质:•每个节点的值大于其左子树中任意节点的值;•每个节点的值小于其右子树中任意节点的值;•左子树和右子树也都是二叉搜索树。

二叉搜索树常用于快速查找元素,插入和删除操作的时间复杂度都为O(log n)。

2.3.2 平衡二叉树(Balanced Binary Tree)平衡二叉树是指左子树和右子树的高度差不超过1的二叉树。

平衡二叉树的性质使得其插入、删除操作的时间复杂度保持在 O(log n)。

2.3.3 堆(Heap)堆是一种特殊的二叉树,分为最大堆和最小堆两种。

实验四二叉树的应用

实验四二叉树的应用

实验四二叉树的应用一、实验目的1.进一步掌握指针变量的含义。

2.掌握二叉树的结构特征,以及各种存储结构的特点及使用范围。

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

二、实验内容1,创建二叉树的二叉链表存储,并中序遍历显示。

参考下面提供的数据类型和函数。

typedef char elemtype;typedef struct BiTNode{elemtype data;struct BiTNode *lchild;*rchild; /*左右孩子指针*/}BiTNode,*BiTree;BiTree CreateBinTree(){/*以加入结点的先序序列输入,构造二叉链表*/BiTree T;elemtype ch;if(*s=='\0') T=NULL;ch=*s;s++;if (ch=='0') T=NULL; /*读入0时,将相应结点置空*/else {T=(BiTNode *)malloc(sizeof(BiTNode)); /*生成结点空间*/ T->data=ch;T->lchild=CreateBinTree(); /*构造二叉树的左子树*/T->rchild=CreateBinTree(); /*构造二叉树的右子树*/}return T;}2.统计其中结点数和叶子结点数;三、实验要求1. 写出C语言程序,并加注释。

2.按前序序列输入结点,AB00G000CE00F00,并说明0的作用;3. 按照你二叉树的操作需要,重新改写主程序并运行,打印出文件清单和运行结果4.收获体会。

二叉树实现及应用实验报告

二叉树实现及应用实验报告

二叉树实现及应用实验报告实验名称:二叉树实现及应用实验目的:1. 实现二叉树的创建、插入和删除操作。

2. 学习二叉树的遍历方法,并能够应用于实际问题。

3. 掌握二叉树在数据结构和算法中的一些常用应用。

实验内容:1. 实现二叉树的创建、插入和删除操作,包括二叉树的构造函数、插入函数和删除函数。

2. 学习二叉树的三种遍历方法:前序遍历、中序遍历和后序遍历,并应用于实际问题。

3. 掌握二叉树的一些常用应用,如二叉搜索树、平衡二叉树和哈夫曼树等。

实验步骤:1. 创建二叉树的结构体,包括树节点和树的根节点。

2. 实现二叉树的构造函数,用于创建二叉树的根节点。

3. 实现二叉树的插入函数,用于将元素插入到二叉树中的合适位置。

4. 实现二叉树的删除函数,用于删除二叉树中的指定元素。

5. 学习并实现二叉树的前序遍历、中序遍历和后序遍历函数。

6. 运用二叉树的遍历方法解决实际问题,如查找二叉树中的最大值和最小值。

7. 学习并应用二叉搜索树、平衡二叉树和哈夫曼树等常用二叉树结构。

实验结果:1. 成功创建、插入和删除二叉树中的元素,实现了二叉树的基本操作。

2. 正确实现了二叉树的前序遍历、中序遍历和后序遍历,并能够正确输出遍历结果。

3. 通过二叉树的遍历方法成功解决了实际问题,如查找二叉树中的最大值和最小值。

4. 学习并熟练应用了二叉搜索树、平衡二叉树和哈夫曼树等常用二叉树结构,丰富了对二叉树的理解。

实验分析:1. 二叉树是一种重要的数据结构,具有较好的数据存储和查找性能,广泛应用于计算机科学和算法领域。

2. 通过实验,我们深入了解了二叉树的创建、插入和删除操作,以及前序遍历、中序遍历和后序遍历的原理和应用。

3. 实际问题往往可以转化为二叉树的遍历问题进行求解,通过实验,我们成功应用了二叉树的遍历方法解决了实际问题。

4. 熟练掌握二叉搜索树、平衡二叉树和哈夫曼树的原理和应用,对于提高我们在数据结构和算法方面的设计能力具有重要意义。

实验四:二叉树的基本操作和应用

实验四:二叉树的基本操作和应用
printf("*********************************************\n");
while(1)
{
scanf("%d",&i);
if(i==1)
{
printf("Preorder :");
PreOrder(root);
printf("\n");
}
if(i==2)
{
struct Node * RChild;
}BiTree;
BiTree* BuildTree(BiTree *B)
{
char ch;
ch=getchar();
if(ch=='0')
B=NULL;
else
{
B=(BiTree *)malloc(sizeof(BiTree));
B->data=ch;
B->LChild=BuildTree(B->LChild);
{
PostOrder(root ->LChild);
PostOrder(root ->RChild);
printf("%c",root->data);
}
}
void End(BiTree *root)
{
printf("End");
}
void Set(BiTree *root)
{ int i;
printf("*********************************************\n");
B->RChild=BuildTree(B->RChild);

二叉树的应用实验报告

二叉树的应用实验报告

实验报告课程名称____数据结构上机实验__________ 实验项目______二叉树的应用 ____________实验仪器________PC机___________________系别____________________________专业_____________________________班级/学号____________________________学生_____________________________实验日期_______________________成绩_______________________指导教师_______________________实验三.二叉树的应用1.实验目的:掌握二叉树的链式存储结构和常用算法。

利用哈夫曼树设计最优压缩编码。

2.实验容:1)编写函数,实现建立哈夫曼树和显示哈夫曼树的功能。

2)编写函数,实现生成哈夫曼编码的功能。

3)编写主函数,从终端输入一段英文文本;统计各个字符出现的频率,然后构建哈夫曼树并求出对应的哈夫曼编码;显示哈夫曼树和哈夫曼编码。

选做容:修改程序,选择实现以下功能:4)编码:用哈夫曼编码对一段英文文本进行压缩编码,显示编码后的文本编码序列;5)统计:计算并显示文本的压缩比例;6)解码:将采用哈夫曼编码压缩的文本还原为英文文本。

3.算法说明:1)二叉树和哈夫曼树的相关算法见讲义。

2)编码的方法是:从头开始逐个读取文本字符串中的每个字符,查编码表得到它的编码并输出。

重复处理直至文本结束。

3)解码的方法是:将指针指向哈夫曼树的树根,从头开始逐个读取编码序列中的每位,若该位为1则向右子树走,为0则向左子树走。

当走到叶子节点时,取出节点中的字符并输出。

重新将指针放到树根,继续以上过程直至编码序列处理完毕。

4)压缩比例的计算:编码后的文本长度为编码序列中的0和1,的个数,原文本长度为字符数*8。

两者之比即为压缩比。

4.实验步骤:实现哈夫曼树的编码序列操作:int i=0,j=0;huffnode p;p=tree[2*n-2];//序号2*n-2节点就是树根节点while(hfmstr[i]!='\0')//从头开始扫描每个字符,直到结束{while(p.lchild!=-1&&p.rchild!=-1)if(hfmstr[i]=='0')//为0则向左子树走{p=tree[p.lchild];//取出叶子节点中的字符}else if(hfmstr[i]=='1')//为1则向右子树走{p=tree[p.rchild];//取出叶子节点中的字符}i++;}decodestr[j]=p.data;j++;//对字符进行译码,结果放在decodestr字符串中p=tree[2*n-2];//返回根节点}}程序修改后完整源代码如下:#include <stdio.h>#include <stdlib.h>#include <string.h>#include <limits.h>//专门用于检测整型数据数据类型的表达值围#define N 96 //ASCII字符集包含至多N个可见字符typedef struct //Huffman树节点定义{ char data; //字符值int weight; //权重int lchild; //左子结点int rchild; //右子结点} huffnode; //huffman节点类型struct charcode{ int count; //字符出现的次数(频率)char code[N]; //字符的Huffman编码} codeset[N]; //编码表,长为N,每项对应一个ascii码字符,下标i的项对应ascii编码为i+32的字符huffnode * CreateHufftree(char data[], int weight[], int n) //建立Huffman树的算法{int i,k;int min1,min2,min_i1,min_i2;huffnode *tree;tree=(huffnode *)malloc((2*n-1)*sizeof(huffnode)); //为Huffman树分配2n-1个节点空间for (i=0;i<2*n-1;i++) //初始化,将各字符和其频率填入Huffman树,作为叶子结点{tree[i].lchild=tree[i].rchild=-1;if (i<n) {tree[i].data=data[i];tree[i].weight=weight[i];}else tree[i].data=' ';}for (i=n;i<2*n-1;i++) ////合并两棵树,作n-1遍min1=min2=INT_MAX; //INT_MAX为最大值min_i1=min_i2=-1;for (k=0;k<i;k++) ////查找定位两个最小权重节点if (tree[k].weight>=0) //仅在根节点中找if (tree[k].weight<min1){min2=min1;min_i2=min_i1;min1=tree[k].weight;min_i1=k;}elseif (tree[k].weight<min2) {min2=tree[k].weight;min_i2=k;}tree[i].weight=min1+min2; // 合并tree[min_i1].weight *= -1;tree[min_i2].weight *= -1;tree[i].lchild=min_i1;tree[i].rchild=min_i2;return tree;}void CreateHuffcode(huffnode tree[], int i, char s[])//已知tree[i]节点的编码序列为s,求该节点下所有叶子节点的编码序列。

二叉树及其应用实验报告

二叉树及其应用实验报告
实验时间:10月28日3、4节星期五
实验地点:一号教学楼微机室
实验名称:二叉树及其应用
实验目的:熟悉各种存储结构及应用二叉树解决具体问题
实验环境:微机室、DEV-C++
实验步骤:1、确定基本思路和设计思想
2、确定程序主题
3、进行编程设计
4、调试程序
5、分析程序错误,编译调试
6、总结经验
实验体会:二叉树的存储、遍历等非常多,但只要实际掌握了二叉树的原理,在课堂上认真听老师讲课,在编程时其实可以减少好多工作量。只要认真思考,参考一些案例,也可以调试好自己的程序。
void preorder_btree(b_tree root)
{
b_tree p=root;
if(p!=null)
{
printf("%3c",p->data);
preorder_btree(p->left);
preorder_btree(p->right);
}
}
/*中序遍历打印二叉排序树*/
void inorder_btree(b_tree root)
b_trБайду номын сангаасe p=root;
if(p!=null)
{
postorder_btree(p->left );
postorder_btree(p->right );
printf("%3c",p->data );
}
}
在调试程序的过程中,这几段关于二叉树遍历的原理其实老师都讲过,在调试程序的过程中,加深了对二叉树的遍历的理解,有助于更好地学习二叉树、应用二叉树。
{
b_tree p=root;

实验四、二叉树

实验四、二叉树

实验四二叉树的应用一、实验目的1)了解二叉树的概念、性质。

2)二叉树的存储结构及其遍历。

3)理解应用二叉树的程序。

二、实验内容1)二叉树定义及其性质。

二叉树是一种很重要的数据结构。

其特点是每个结点至多只有两棵子树,一棵称为左子树、另一棵称为右子树。

a、二叉树性质1、二叉树的第i层至多有2^(i-1)个结点(i>=1)。

2、深度为k的二叉树至多有2^k-1个结点(k>=1)。

b、二叉树的两种特殊形式。

1、满二叉树。

它是高为k,且有2^k -1个结点的二叉树。

其特点是每一层上的结点数都是最大结点数。

2、完全二叉树性质1)叶子结点只可能在层次最大的两层上出现。

2)对任意一结点,若其右分支下的子孙的最大层次数为x,则其左分支下的子孙的最大层次数不小于x。

2)二叉树的存储结构和遍历。

3)一般二叉树的链式存储结构三、程序结构、1)链式存储的二叉树的建立#define NULL 0struct link{struct link *lchild;struct link *rchild;char data;};struct link *root;char ch;struct link *newnode(){return((struct link * ) malloc (sizeof(struct link)));}struct link *creattree(){struct link *tree;scanf("%c",&ch);printf("%c",ch);if(ch!='.'){tree=newnode();tree->data=ch;tree->lchild=creattree(); tree->rchild=creattree(); }elsetree=NULL;return(tree);}2)二叉树的遍历a、先序遍历:若二叉树为空,返回;否则,访问根结点,先序遍历左子数,先序遍历右子数。

国家开放大学《数据结构》课程实验报告(实验4——二叉树)参考答案

国家开放大学《数据结构》课程实验报告(实验4——二叉树)参考答案
《数据结构》课程实验报告
(实验4二叉树)
学生姓名
学 号
班 级
指导老师
实验名称
实验成绩
实验报告
实ቤተ መጻሕፍቲ ባይዱ



实验目的:
(1)根据数组tree,建立与该二叉树对应的链式存储结构。
(2)对该二叉树采用中序遍历法显示遍历结果。
实验要求:
(1)在主函数中,通过键盘输入建立设定的完全二叉树的顺序存储结构。
(2)设计子函数,其功能为将顺序结构的二叉树转化为链式结构。
(2)中序遍历采用递归算法,即中序遍历左子树、访问根结点、中序遍历右子树。




程序代码:
/*实验3.1二叉树的顺序存储结构和链式存储结构*/
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 20
/*二叉树链式存储结构结点定义*/
typedef struct BTreeNode






指导教师 日期
(3)设计子函数,其功能为对给定二叉树进行中序遍历,显示遍历结果。
(4)通过实例判断算法和相应程序的正确性。
实验基本原理:
(1)顺序存储的二叉树转化为链式存储结构,采用递归算法,递归函数的形式为Creab(tree,n,i,b),其中形参:tree为顺序存储二叉树的数组,n为二叉树的结点数,i是二叉树某结点在数组tree中的下标(初始值为1),b为要建立的链式存储二叉树结点指针。转化时,首先建立*b结点,将tree[i]的值赋给*b的数据域,再调用递归函数分别构造左子树和右子树。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

姓名学号序#include"DataStructure_BinaryTree.h"//数据结构第六章树与二叉树函数的定义及声明using namespace std;int main(void){system("title 数据结构实验实验四:树和二叉树及其应用(I) "); //设置cmd窗口标题 system("color F1"); //设置控制台窗口的背景色和前景色system("date /T"); //输出当前的日期print();cout << "实验内容一:树的遍历" << endl;BiTree T;int num = 0;cout << " 二叉树的建立:" << endl;cout << " 输入二叉树数据:";GreateBiTree(T); //先序建立二叉树cout << " 二叉树的遍历" << endl << " 【递归遍历】 ";cout << endl << "> 先序遍历:";PreOrderTraverse(T, PrintElement); //先序遍历二叉树cout << endl << "> 中序遍历:";InOrderTraverse(T, PrintElement); //中序遍历二叉树cout << endl << "> 后序遍历:";PostOrderTraverse(T, PrintElement); //后序遍历二叉树cout << endl << "> 层序遍历:" << endl;LevelOrderTraverse(T, PrintElement); //层序遍历二叉树cout << endl<< " 【非递归遍历】";cout << endl << "> 先序遍历:";PreOrderTraverseNonRec(T, PrintElement); //先序遍历二叉树cout << endl << "> 中序遍历:";InOrderTraverseNonRec(T, PrintElement); //中序遍历二叉树cout << endl << "> 后序遍历:";PostOrderTraverseNonRec(T, PrintElement); //后序遍历二叉树cout << endl << "> 层序遍历:";LevelOrderTraverseNonRec(T, PrintElement);//层序遍历二叉树print();cout << endl << "实验内容二:二叉树的基本操作";cout << endl << "<1> 二叉树的深度:" << BiTDepth(T) << endl;LeafTNodeNum(T, num);cout << "<2> 二叉树中叶子结点的数目:" << num << endl;cout << "<3> 交换左右子树:" << endl;ExchangeBiTree(T);cout << " 交换后的二叉树:" << endl;LevelOrderTraverse(T, PrintElement); //层序遍历二叉树BiTree root;TElemType x;int depth;cout << "<4> 查找指定节点的根子树:" << endl << " 请输入需要查找的根节点:x = ";cin >> x;PreOrderLocate(T, x, root); //先序查找以元素值为x的结点为子树,并以root指向其根子树cout << " 以元素x为根节点的根子树:" << endl;LevelOrderTraverse(root, PrintElement); //层序遍历二叉树ChildBiTreeDepth(T, x, depth);cout << "<5> 查找指定节点的根子树的深度:" << endl << " 以元素x为根节点的根子树的深度:" << depth << endl;cout << "<6> 判断根子树是否为完全二叉树:" << endl;if (CompleteBiTree(root))cout << " 以元素x为根节点的根子树是完全二叉树" << endl;elsecout << " 以元素x为根节点的根子树不是完全二叉树" << endl;DelChildBiTree(T, x);cout << "<7> 删除二叉树:" << endl;cout << " 删除以元素x为根节点的根子树后的二叉树:" << endl;LevelOrderTraverse(T, PrintElement); //层序遍历二叉树if (CompleteBiTree(T))cout << " 删除以元素x为根子树后的二叉树是完全二叉树" << endl;elsecout << " 删除以元素x为根子树后的二叉树不是完全二叉树" << endl;DestoryBiTree(T); //销毁二叉链表TDestoryBiTree(root); //销毁二叉树rootreturn 0;}2.头文件”ADT.h”的部分程序如下:#ifndef ADT_H_#define ADT_H_/* ------二叉树数据类型定义------ */typedef char TElemType; //顺序表中元素的数据类型/* ------二叉树链式结构类型定义------ */typedef struct BiTNode{TElemType data; //二叉树结点数据struct BiTNode *lchild, *rchild; //二叉树结点指针}BiTNode, *BiTree; //二叉树结点类型及结构体指针类型/************************栈和队列*************************//* ------栈数据类型定义------ */typedef BiTree SElemType; //顺序表中元素的数据类型/* ------队列数据类型定义------ */typedef BiTree QElemType; //顺序表中元素的数据类型#endif/* ADT_H_ */3.头文件"DataStructure_StackQueue.h"中部分函数定义如下:#include<stdio.h>#include<malloc.h>#include"ADT.h"#include"DataStructure_StackQueue.h" //数据结构第三章栈和队列相关函数的定义及声明/************************************************************* 功能函数声明区************************************************************/Status GreateBiTree(BiTree &T); //按先序输入二叉树中节点的值,'#'字符表示空树,构造二叉链表树TStatus PreOrderTraverse(BiTree T, Status(*Visit)(TElemType e)); //先序递归遍历二叉树TStatus InOrderTraverse(BiTree T, Status(*Visit)(TElemType e)); //中序递归遍历二叉树T Status PostOrderTraverse(BiTree T, Status(*Visit)(TElemType e)); //递归后序遍历二叉树TStatus LevelOrderTraverse(BiTree T, Status(*Visit)(TElemType e)); //递归层序遍历二叉树T Status PreOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e)); //先序非递归遍历二叉树TStatus InOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e)); //中序非递归遍历二叉树TStatus PostOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e)); //后序非递归遍历二叉树TStatus LevelOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e));//层序非递归遍历二叉树Tint BiTDepth(BiTree &T); //求二叉树的深度Status TraverseLevel(BiTree root, int level,Status(*Visit)(TElemType e));//遍历以roo为根节点中的level层的所以节点(从左到右),成功返回1,失败返回0Status PreOrderLocate(BiTree &T, TElemType e, BiTree &T1);//先序查找以元素值为e的结点为子树,并以T1指向其根子树Status ChildBiTreeDepth(BiTree &, TElemType , int &); //求以元素值x的节点的根子树的深度Status InitBiTree(BiTree &T); //初始化二叉链表TStatus BiTreeEmpty(BiTree T); //判断二叉树是否为空,若为空则返回TRUE, 否则返回FALSE Status DestoryBiTree(BiTree &T); //销毁二叉树TStatus DelBiTree(BiTree &); //删除二叉链表TStatus DelChildBiTree(BiTree &, TElemType e); //删除以元素值为e的结点为根子树Status CompleteBiTree(BiTree T); //判断二叉树是否为完全二叉树Status ExchangeBiTree(BiTree &T); //先序交换二叉树的左右子树Status LeafTNodeNum(BiTree T, int &num); //求二叉树的叶子结点的个数,叶子结点个数numStatus CopyBiTree(BiTree &T1, BiTree &T2); //复制二叉树Status PrintElement(TElemType e); //二叉树数据元素操作应用函数/************************************************************* 功能函数定义区************************************************************//** 函数原型:Status PrintElement(TElemType e)* 函数功能:二叉树数据元素操作应用函数* 入口参数:TElemType类型的数据* 出口参数:返回函数结果状态*/Status PrintElement(TElemType e){printf("%c ",e);return OK;} //PrintElement/** 函数原型:Status GreateBiTree(BiTree &T)* 函数功能:按先序输入二叉树中结点的值,'#'字符表示空树,构造二叉链表树T* 入口参数:BiTree类型树T* 出口参数:返回函数结果状态*/Status GreateBiTree(BiTree &T){TElemType data;scanf_s("%c", &data);if (data == '#')T = NULL;else{if (!(T = (BiTree)malloc(sizeof(BiTNode))))return OVERFLOW;T->data = data;GreateBiTree(T->lchild);GreateBiTree(T->rchild);}return OK;} //GreateBiTree/** 函数原型:Status PreOrderTraverse(BiTree T, Status(*Visit)(TElemType e))* 函数功能:先序遍历二叉树T的递归算法,对每个数据元素调用函数Visit一次且仅一次* 入口参数:二叉链表T,Visit是对数据元素操作的应用函数* 出口参数:返回函数结果状态*/Status PreOrderTraverse(BiTree T, Status(*Visit)(TElemType e)){if (T) //判断是否为空树{if (Visit(T->data)) //访问根结点if (PreOrderTraverse(T->lchild, Visit)) //先序遍历左子树if (PreOrderTraverse(T->rchild, Visit)) //先序遍历右子树return OK;return ERROR; //访问根结点失败}elsereturn OK; //访问根结点失败,不能返回ERROR,返回OK,保证所有节点都能被访问} // PreOrderTraverse/** 函数原型:Status PreOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e))* 函数功能:先序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit一次且仅一次* 入口参数:二叉链表T,Visit是对数据元素操作的应用函数* 出口参数:返回函数结果状态*/Status PreOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e)){BiTree p;LinkStack S;InitStack_L(S);p = T;while (p || !StackEmpty_L(S)){if (p){if (!Visit(p->data)) //如果根指针不空,访问根结点return ERROR;Push_L(S, p); //根指针域压栈,继续遍历左子树p = p->lchild;}else//根指针已空,本左子树遍历完毕{Pop_L(S, p); //根指针域退栈,继续遍历右子树p = p->rchild;}}return OK;} // PreOrderTraverseNonRec/** 函数原型:Status InOrderTraverse(BiTree T, Status(*Visit)(TElemType e))* 函数功能:中序遍历二叉树T的递归算法,对每个数据元素调用函数Visit一次且仅一次* 入口参数:二叉链表T,Visit是对数据元素操作的应用函数* 出口参数:返回函数结果状态*/Status InOrderTraverse(BiTree T, Status(*Visit)(TElemType e)){if (T) //判断是否为空树{if (InOrderTraverse(T->lchild, Visit)) //中序遍历左子树if (Visit(T->data)) //访问根结点if (InOrderTraverse(T->rchild, Visit)) //中序遍历右子树return OK;return ERROR; //访问失败}elsereturn OK; //访问失败} // InOrderTraverse/** 函数原型:Status InOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e))* 函数功能:中序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit一次且仅一次* 入口参数:二叉链表T,Visit是对数据元素操作的应用函数* 出口参数:返回函数结果状态*/Status InOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e)){BiTree p;LinkStack S;InitStack_L(S);p = T;while (p || !StackEmpty_L(S)){if (p){Push_L(S, p); //根指针进栈,遍历左子树p = p->lchild;}else{Pop_L(S, p); //根指针退栈,访问根结点,遍历右子树if (!Visit(p->data))return ERROR;p = p->rchild;}}return OK;} // InOrderTraverseNonRec/** 函数原型:Status PostOrderTraverse(BiTree T, Status(*Visit)(TElemType e))* 函数功能:后序遍历二叉树T的递归算法,对每个数据元素调用函数Visit一次且仅一次* 入口参数:二叉链表T,Visit是对数据元素操作的应用函数* 出口参数:返回函数结果状态*/Status PostOrderTraverse(BiTree T, Status(*Visit)(TElemType e)){if (T) //判断是否为空树{if (PostOrderTraverse(T->lchild, Visit)) //后序遍历左子树if (PostOrderTraverse(T->rchild, Visit)) //后序遍历右子树if (Visit(T->data)) //访问根结点return OK;return ERROR; //访问失败}elsereturn OK;} // PostOrderTraverse/** 函数原型:Status PostOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e))* 函数功能:后序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit一次且仅一次* 入口参数:二叉链表T,Visit是对数据元素操作的应用函数* 出口参数:返回函数结果状态*/Status PostOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e)){BiTree p, q, last;LinkStack S;q = last = NULL;InitStack_L(S);p = T;while (p || !StackEmpty_L(S)){while (p) //根指针不空,则进栈,遍历左子树{Push_L(S, p);p = p->lchild;}GetTop_L(S, q);if (!q->rchild || q->rchild == last) //根节点能被访问的条件是右子树为空或已被访问过{if (!Visit(q->data))return ERROR;Pop_L(S, last);}elsep = q->rchild;}return OK;} // PostOrderTraverseNonRec/** 函数原型:Status LevelOrderTraverse(BiTree T, Status(*Visit)(TElemType e))* 函数功能:层序遍历二叉树T的递归算法,对每个数据元素调用函数Visit一次且仅一次* 入口参数:二叉链表T,Visit是对数据元素操作的应用函数* 出口参数:返回函数结果状态*/Status LevelOrderTraverse(BiTree T, Status(*Visit)(TElemType e)){if (!T)return ERROR;for (int level = 0;; level++){if (!TraverseLevel(T, level, Visit))break;printf("\n");}return OK;} //LevelOrderTraverse/** 函数原型:Status LevelOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e)) * 函数功能:层序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit一次且仅一次* 入口参数:二叉链表T,Visit是对数据元素操作的应用函数* 出口参数:返回函数结果状态*/Status LevelOrderTraverseNonRec(BiTree T, Status(*Visit)(TElemType e)){BiTree p;LinkQueue Q;InitQueue_L(Q);if (T)EnQueue_L(Q, T);while (!QueueEmpty_L(Q)){DeQueue_L(Q, p);Visit(p->data);if (p->lchild)EnQueue_L(Q, p->lchild);if (p->rchild)EnQueue_L(Q, p->rchild);}return OK;} // LevelOrderTraverseNonRec/** 函数原型:Status TraverseLevel(BiTree root,int level,Status(*Visit)(TElemType e))* 函数功能:遍历以roo为根节点中的level层的所以节点(从左到右),成功返回1,失败返回0* 入口参数:root:二叉树的根结点,level:层次数,根结点为第0层* 出口参数:返回函数结果状态*/Status TraverseLevel(BiTree root, int level, Status(*Visit)(TElemType e)){if (!root || level < 0)return ERROR;if (level == 0)return Visit(root->data);elsereturn TraverseLevel(root->lchild, level - 1, Visit) + TraverseLevel(root -> rchild, level - 1, Visit);} //PrintBiTreeLevel/** 函数原型:int BiTDepth(BiTree T)* 函数功能:求二叉树的深度* 入口参数:二叉链表T* 出口参数:二叉链表的深度*/int BiTDepth(BiTree &T){int ldepth, rdepth;if (!T)return 0;else{ldepth = BiTDepth(T->lchild) + 1;rdepth = BiTDepth(T->rchild) + 1;return ldepth > rdepth ? ldepth : rdepth;}} //BiTDepth/** 函数原型:Status CompleteBiTree(BiTree T)* 函数功能:判断二叉树是否为完全二叉树* 入口参数:二叉链表T* 出口参数:返回函数结果状态*/Status CompleteBiTree(BiTree T){int d;if (T){d = BiTDepth(T->lchild) - BiTDepth(T->rchild);if (d<0 || d>1)return ERROR;else{if (CompleteBiTree(T->lchild) && CompleteBiTree(T->rchild))return OK;elsereturn ERROR;}}return OK;} //CompleteBiTree/** 函数原型:Status LeafTNodeNum(BiTree T,int &num)* 函数功能:求二叉树的叶子结点的个数,叶子结点个数num* 入口参数:二叉链表T* 出口参数:返回函数结果状态*/Status LeafTNodeNum(BiTree T,int &num){if (!T)return ERROR;else{if (!T->lchild&&!T->rchild)num++;LeafTNodeNum(T->lchild, num);LeafTNodeNum(T->rchild, num);}return OK;} //LeafTNodeNum1、此次实验完成了对二叉树的遍历操作和二叉树的一些基本操作。

相关文档
最新文档