实验6:二叉树及其应用
实验6:二叉树及其应用
一、实验目的
树是数据结构中应用极为广泛的非线性结构,本单元的实验达到熟悉二叉树的存储结构的特性,以及如何应用树结构解决具体问题。
二、问题描述
首先,掌握二叉树的各种存储结构和熟悉对二叉树的基本操作。其次,以二叉树表示算术表达式的基础上,设计一个十进制的四则运算的计算器。
如算术表达式:a+b*(c-d)-e/f
三、实验要求
1、 如果利用完全二叉树的性质和二叉链表结构建立一棵二叉树,分别计算
a) 统计叶子结点的个数。 b) 求二叉树的深度。 2、 十进制的四则运算的计算器可以接收用户来自键盘的输入。 3、 由输入的表达式字符串动态生成算术表达式所对应的二叉树。 4、 自动完成求值运算和输出结果。
四、实验环境
PC 微机
DOS 操作系统或 Windows 操作系统
Turbo C 程序集成环境或 Visual C++ 程序集成环境
五、实验步骤
1、根据二叉树的各种存储结构建立二叉树;
2、设计求叶子结点个数算法和树的深度算法;
3、根据表达式建立相应的二叉树,生成表达式树的模块;
-
+
/
a
*
b
-
e
f
C
d
4、根据表达式树,求出表达式值,生成求值模块;
5、程序运行效果,测试数据分析算法。
六、功能分析
存储结构
typedef union{
int Operator; // 操作符
float Operand; // 操作数
}Int_Float;
//表达式树
typedef struct BinaryTreeNode{
Int_Float Data; //数据域
int IsOperator; //判断是不是操作数的标志位
struct BinaryTreeNode *RChild;//左子树
struct BinaryTreeNode *LChild;//右子树
}BiTreeNode, *lpBiTreeNode;
//栈的定义
typedef struct {
lpBiTreeNode *base;
lpBiTreeNode *top;
int stacksize;
函数一览表
lpBiTreeNode GetTop( SqStack s );//取栈顶结点函数
int IsEmpty( SqStack s );//判空函数
int InitStack( SqStack &s );//初始化栈函数
int Pop( SqStack &s, lpBiTreeNode &e );//出栈函数
int Push( SqStack &s, lpBiTreeNode e );//入栈函数
int In( int c, int* op );// 判断c是否在op中
int Precede( int theta1, int theta2 );//比较运算符号的优先级
int isNum( int c );//判断是不是数
int GetInput(Int_Float *Result);//读入输入的数
lpBiTreeNode CreateBiTree();//创建二叉树
bool calculate(lpBiTreeNode Root, float *result);//计算二叉树化表达式的值int getLeafNum(lpBiTreeNode Root);//计算二叉树的叶子结点数
计算叶子节点数的算法分析计算二叉树深度的算法分析
递归,核心在于
num=numleft+numright
Int num(二叉树 *p){
If(空树)return 0;
Else if(一个节点的树) return 1;
Else{
Return num(num(左子树)+num(右子树));}
}
递归,核心在于
depth=max(leftdepth,righydepth)+1
Int depth(二叉树 *p){
If(空树)return 0;
Else if(一个节点的树) return 1;
Else{
Return
max(depth(左子树),depth(右子树)+1);
}
}
七、程序代码
#include
#include
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define ERROR 0
#define NUMBER 1
#define SIMBLE 2
int OP[8] = { '+', '-', '*', '/', '(', ')', '#', 0 };//运算符数组
//共用体
typedef union
{
int Operator; // 操作符
float Operand; // 操作数
}Int_Float;
//表达式树
typedef struct BinaryTreeNode
{
Int_Float Data; //数据域
int IsOperator; //判断是不是操作数的标志位
struct BinaryTreeNode *RChild;//左子树
struct BinaryTreeNode *LChild;//右子树
}BiTreeNode, *lpBiTreeNode;
//栈的定义
typedef struct {
lpBiTreeNode *base;
lpBiTreeNode *top;
int stacksize;
}SqStack;
//函数声明区
lpBiTreeNode GetTop( SqStack s );//取栈顶结点函数
int IsEmpty( SqStack s );//判空函数
int InitStack( SqStack &s );//初始化栈函数
int Pop( SqStack &s, lpBiTreeNode &e );//出栈函数
int Push( SqStack &s, lpBiTreeNode e );//入栈函数
int In( int c, int* op );// 判断c是否在op中
int Precede( int theta1, int theta2 );//比较运算符号的优先级
int isNum( int c );//判断是不是数
int GetInput(Int_Float *Result);//读入输入的数
lpBiTreeNode CreateBiTree();//创建二叉树
bool calculate(lpBiTreeNode Root, float *result);//计算二叉树化表达式的值int getLeafNum(lpBiTreeNode Root);//计算二叉树的叶子结点数
int getDepth(lpBiTreeNode Root);//计算二叉树的深度
int main()//主函数
{
lpBiTreeNode Root;//二叉树
float result; //表达式运算结果
if( Root = CreateBiTree() )//若创建二叉树失败则不会执行if操作
{
printf( "二叉树叶子数= %d\n", getLeafNum(Root) );
printf( "二叉树的深度= %d\n", getDepth(Root) );
if( calculate(Root, &result) )//计算结果
{
printf("表达式的值= %0.2f\n", result);
}
else
printf("ERROR");
}
else
printf("INPUT ERROR\n");
printf("********************************\n");
return 0;
}
lpBiTreeNode GetTop( SqStack s )
{
lpBiTreeNode e;
if( s.top == s.base )//栈为空情况
return NULL;
e = *(s.top -1);//top指针指向栈顶元素的后一个空间
return e;
}
int IsEmpty( SqStack s )
{
if( s.top == s.base )//栈为空
return 1;
else
return 0;
}
int InitStack( SqStack &s )
{
s.base = (lpBiTreeNode *)malloc( STACK_INIT_SIZE*sizeof(lpBiTreeNode) );//malloc 栈基址空间
if(!s.base)//分配空间失败
return 0;
s.top = s.base;//栈顶指针
s.stacksize = STACK_INIT_SIZE;//初始化栈大小
return 1;
}
int Pop( SqStack &s, lpBiTreeNode &e )
{
if( s.top == s.base )//空栈
return 0;
s.top --;//top指针前移
e = *s.top;//取栈顶元素
return 1;
}
int Push( SqStack &s, lpBiTreeNode e )//入栈函数
{
if( s.top - s.base >= s.stacksize )//空间已满
{
s.base = (lpBiTreeNode *)realloc( s.base, (s.stacksize + STACKINCREMENT)*sizeof(lpBiTreeNode) );//重新分配空间
if(!s.base)
return 0;
s.top = s.base + s.stacksize;//栈顶指针位置
s.stacksize += STACKINCREMENT;//新栈的大小
}
*s.top = e;//元素e入栈
s.top ++;//栈顶指针后移
return 1;
}
int In( int c, int* op ) // 判断c 是否在op 中,op为以结尾的数组
{
while( *op != 0 )//比较所有元素,最后一个为0
{
if( c == *op )//相等,存在 return 1
return 1;
op ++;//op指针后移
}
return 0;
}
int Precede( int theta1, int theta2 )//比较优先级
{
int i, j;
int op_look[7][7] =
{ { '>', '>', '<', '<', '<', '>', '>' }, { '>', '>', '<', '<', '<', '>', '>' }, { '>', '>', '>', '>', '<', '>', '>' }, { '>', '>', '>', '>', '<', '>', '>' }, { '<', '<', '<', '<', '<', '=', ' ' }, { '>', '>', '>', '>', ' ', '>', '>' }, { '<', '<', '<', '<', '<', ' ', '=' } };//运算符优先级二维数组
switch( theta1 )//定位theta1
{
case '+':
i = 0;
break;
case '-':
i = 1;
break;
case '*':
i = 2;
break;
case '/':
i = 3;
break;
case '(':
i = 4;
break;
case ')':
i = 5;
break;
case '#':
i = 6;
break;
default:
return 0;
}
switch( theta2 )//定位theta2
{
case '+':
j = 0;
break;
case '-':
j = 1;
break;
case '*':
j = 2;
break;
case '/':
j = 3;
break;
case '(':
j = 4;
break;
case ')':
j = 5;
break;
case '#':
j = 6;
break;
default:
return 0;
}
return op_look[i][j];//判断优先级
}
int isNum( int c )//是不是数字
{
if( c >= '0' && c <= '9' )//ascii码
return 1;
else return 0;
}
int GetInput(Int_Float *Result) // 返回值:无,1数字,2符号{
static int buffer = 0; // 缓存存储数字后的符号
int c;
Int_Float result;
int IsNumber = 0; // 是否为数字
int IsFloat = 0; // 是否为小数
int i,t=1;
result.Operand = 0;
if(In(buffer, OP)) // 缓存中有符号
{
result.Operator = buffer;
buffer = 0;
Result->Operator = result.Operator;
return SIMBLE; // 符号
}// 去前导空格
c = getchar();
while ( c == ' ' && c != 10 )
{
c = getchar();
}
while( c != ' ' && c != 10 ) // 不是空格和回车
{
if(isNum(c)) // 是数字
{
IsNumber = 1;
c = c - 48; // 字符到整型
if(IsFloat == 0)
result.Operand = result.Operand*10 + c;
else
{
result.Operand = result.Operand*10 + c;
IsFloat ++;
}
}
else if(c == '.')
{
if(IsFloat != 0) // 两个小数点
{
Result->Operand = 0;
return ERROR;
}
else
IsFloat = 1;
}
else if (In(c, OP))
{
if(IsNumber) // 数字后接符号
{
if(IsFloat == 1)
{
Result->Operand = 0;
return ERROR;
}
else
{
buffer = c;
for(i=0; i t*=10; Result->Operand = result.Operand/(float)t; return NUMBER; // 数字 } } else { Result->Operator = c; return SIMBLE; // 符号 } } c = getchar(); } buffer = 0; if(IsNumber)//处理数字 { if(IsFloat == 1) { Result->Operand = 0; return ERROR; } else { for(i=0; i t*=10; Result->Operand = result.Operand/(float)t; } } else if(result.Operand == 0)//错误输入 { Result->Operand = 0; return ERROR; } else//处理符号 { Result->Operator = result.Operator; return SIMBLE; } } lpBiTreeNode CreateBiTree()//创建新的二叉树 { SqStack Operand; // 操作数 SqStack Operator; // 操作符 lpBiTreeNode pNode; lpBiTreeNode theta,a,b; Int_Float c; printf("********************************\n"); printf("QAQ请输入一个算式并以'#'号结尾:\n"); int r = GetInput(&c); InitStack(Operand);//初始化操作数栈 InitStack(Operator);//初始化操作符栈 pNode = (lpBiTreeNode)malloc(sizeof(BiTreeNode)); pNode->Data.Operator = '#'; pNode->IsOperator = 1; pNode->LChild = NULL; pNode->RChild = NULL; Push( Operator, pNode ); while( !( r == SIMBLE && c.Operator == '#') || GetTop(Operator)->Data.Operator != '#' )//处理到# { if(r == ERROR) if( r == NUMBER ) // 是数字 { pNode = (lpBiTreeNode)malloc(sizeof(BiTreeNode)); pNode->Data.Operand = c.Operand; pNode->IsOperator = 0; pNode->LChild = NULL; pNode->RChild = NULL; Push(Operand,pNode); r = GetInput(&c); } else if( r == SIMBLE ) // 是符号 { switch( Precede(GetTop(Operator)->Data.Operator, c.Operator) ) { case '<': // 栈顶元素优先权低 pNode = (lpBiTreeNode)malloc(sizeof(BiTreeNode)); pNode->Data.Operator = c.Operator; pNode->IsOperator = 1; pNode->LChild = NULL; pNode->RChild = NULL; Push( Operator, pNode ); r = GetInput(&c); break; case '=': // '(', ')'相遇,脱括号 Pop( Operator, pNode ); r = GetInput(&c); break; case '>': // 栈顶元素优先权高, 退栈并将运算结果入栈 Pop( Operator, theta ); Pop( Operand, b); Pop( Operand, a); theta->LChild = a; theta->RChild = b; Push(Operand, theta); break; } } } return GetTop(Operand); } bool calculate(lpBiTreeNode Root, float *result)//计算二叉树的值 { float resultLchild; float resultRchild; if( Root != NULL )//非空 { if(Root->LChild == NULL && Root->RChild == NULL)//叶子节点 { *result = Root->Data.Operand; return true; } else if(Root->LChild == NULL || Root->RChild == NULL)//不可能出现单子树情况return false; else//左右子树都存在的情况,递归计算 { switch (Root->Data.Operator)//取操作符 { case '+': if( calculate(Root->LChild, &resultLchild)==false ) return false; if( calculate(Root->RChild, &resultRchild)==false ) return false; *result = resultLchild + resultRchild; //该二叉树的值等于左子树的值加上右子树的值 break; case '-': if( calculate(Root->LChild, &resultLchild)==false ) return false; if( calculate(Root->RChild, &resultRchild)==false ) return false; *result = resultLchild - resultRchild; //该二叉树的值等于左子树的值减去右子树的值 break; case '*': if( calculate(Root->LChild, &resultLchild)==false ) return false; if( calculate(Root->RChild, &resultRchild)==false ) return false; *result = resultLchild * resultRchild; //该二叉树的值等于左子树的值乘上右子树的值 break; case '/': if( calculate(Root->LChild, &resultLchild)==false ) return false; if( calculate(Root->RChild, &resultRchild)==false ) return false; *result = resultLchild / resultRchild; //该二叉树的值等于左子树除以加上右子树的值 break; } } } return true; } int getLeafNum(lpBiTreeNode Root)//计算叶子节点数 { int LeafnumLchild;//左子树的叶子结点数 int LeafnumRchild;//右左子树的叶子结点数 if( Root != NULL )//非空 { if(Root->LChild == NULL && Root->RChild == NULL) //该结点是叶子节点 return 1; else { LeafnumLchild = getLeafNum(Root->LChild);//递归计算左子树的num LeafnumRchild = getLeafNum(Root->RChild);//递归计算右子树的num return LeafnumLchild + LeafnumRchild;//总的叶子节点数等于左子树的加上右子树的 } } return 0; } int getDepth(lpBiTreeNode Root)//计算二叉树的深度 { int LeafDepthL;//左子树的深度 int LeafDepthR;//右子树的深度 if( Root != NULL )//非空 { if(Root->LChild == NULL && Root->RChild == NULL) //叶子结点 return 1; else { LeafDepthL = getDepth(Root->LChild);//左子树的深度 LeafDepthR = getDepth(Root->RChild);//右子树的深度 return 1 + (LeafDepthL>LeafDepthR?LeafDepthL:LeafDepthR);//实际深度等于左、右子树的最大深度加上1 } } return 0; } 六、测试数据 1、输入数据:2.2*(3.1+1.20)-7.5/3 正确结果:6.96 2、输入数据:(1+2)*3+(5+6*7); 正确输出:56 八、实验总结 在实现int getDepth(lpBiTreeNode Root)//计算二叉树的深度、int getLeafNum(lpBiTreeNode Root)//计算叶子节点数函数时,都用到了递归的思想。 其实比较奇怪,因为递归的时候总是默认需要用的值总是已知的,比如计算叶子结点数时直接就是等于左子树加右子树的叶子结点数。直观的看上去很难理解,毕竟左右子树的值都是未知的,但是如果把递归表达式展开,展开到最后一层,再来理解就比较清楚,计算机的处理方式和人还是有所不同。 而且递归特比要注意的是边界条件的设定,比如这里面到一棵树为空树,要return 0,一棵树只有一个结点要return 1,边界结点的设定直接决定了递归结果的正确与否,另外建议的是在不确定的时候多设置一些边界处理,以免出现错误,并且可以自己去简单的计算一下在自己设置的边界情况下,n=0,1,2,3时候的值,如果是正确的话一般就没有问题。 实验三二叉树的遍历 一、实验目的 1、熟悉二叉树的结点类型和二叉树的基本操作。 2、掌握二叉树的前序、中序和后序遍历的算法。 3、加深对二叉树的理解,逐步培养解决实际问题的编程能力。 二、实验环境 运行C或VC++的微机。 三、实验内容 1、依次输入元素值,以链表方式建立二叉树,并输出结点的值。 2、分别以前序、中序和后序遍历二叉树的方式输出结点内容。 四、设计思路 1. 对于这道题,我的设计思路是先做好各个分部函数,然后在主函数中进行顺序排列,以此完成实验要求 2.二叉树采用动态数组 3.二叉树运用9个函数,主要有主函数、构建空二叉树函数、建立二叉树函数、访问节点函数、销毁二叉树函数、先序函数、中序函数、后序函数、范例函数,关键在于访问节点 五、程序代码 #include 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); } 二叉树的基本操作实现及其应用 一、实验目的 1.熟悉二叉树结点的结构和对二叉树的基本操作。 2.掌握对二叉树每一种操作的具体实现。 3.学会利用递归方法编写对二叉树这种递归数据结构进行处理的算法。 4.会用二叉树解决简单的实际问题。 二、实验内容 设计程序实现二叉树结点的类型定义和对二叉树的基本操作。该程序包括二叉树结构类型以及每一种操作的具体的函数定义和主函数。 1 按先序次序建立一个二叉树, 2按(A:先序 B:中序 C:后序)遍历输出二叉树的所有结点 以上比做,以下选做 3求二叉树中所有结点数 4求二叉树的深度 三、实验步骤 ㈠、数据结构与核心算法的设计描述 /* 定义DataType为char类型 */ typedef char DataType; /* 二叉树的结点类型 */ typedef struct BitNode { DataType data; struct BitNode *lchild,*rchild; }*BitTree; 相关函数声明: 1、/* 初始化二叉树,即把树根指针置空 */ void BinTreeInit(BitTree *BT) { BT=(BitTree)malloc(sizeof(BitNode)); BT->data=NULL; cout<<"二叉树初始化成功!"< //二叉树的基本操作 #include 实验三二叉树的基本运算 一、实验目的 1、使学生熟练掌握二叉树的逻辑结构和存储结构。 2、熟练掌握二叉树的各种遍历算法。 二、实验内容 [问题描述] 建立一棵二叉树,试编程实现二叉树的如下基本操作: 1. 按先序序列构造一棵二叉链表表示的二叉树T; 2. 对这棵二叉树进行遍历:先序、中序、后序以及层次遍历,分别输出结点的遍历序列; 3. 求二叉树的深度/结点数目/叶结点数目;(选做) 4. 将二叉树每个结点的左右子树交换位置。(选做) [基本要求] 从键盘接受输入(先序),以二叉链表作为存储结构,建立二叉树(以先序来建立), [测试数据] 如输入:ABCффDEфGффFффф(其中ф表示空格字符) 则输出结果为 先序:ABCDEGF 中序:CBEGDFA 后序:CGEFDBA 层序:ABCDEFG [选作内容] 采用非递归算法实现二叉树遍历。 三、实验前的准备工作 1、掌握树的逻辑结构。 2、掌握二叉树的逻辑结构和存储结构。 3、掌握二叉树的各种遍历算法的实现。 一实验分析 本次试验是关于二叉树的常见操作,主要是二叉树的建立和遍历。二叉树的遍历有多种方法,本次试验我采用递归法,递归法比较简单。 二概要设计 功能实现 1.int CreatBiTree(BiTree &T) 用递归的方法先序建立二叉树, 并用链表储存该二叉树 2.int PreTravel(BiTree &T) 前序遍历 3. int MidTravel(BiTree &T) 中序遍历 4.int PostTravel(BiTree &T) 后序遍历 5.int Depth(BiTree &T) //计算树的深度 6.int howmuch(BiTree T,int h) 采用树节点指针数组,用于存放遍历到的元素地址,如果有左孩子,存入地址,j加一,否则没操作,通过访问数组输出层次遍历的结果。k计算叶子数,j为总节点。 7. int exchang(BiTree &T) 交换左右子树,利用递归,当有左右孩子时才交换 三详细设计 #include 实验六:二叉树及其应用 一、实验目的 树是数据结构中应用极为广泛的非线性结构,本单元的实验达到熟悉二叉树的存储结构的特性,以及如何应用树结构解决具体问题。 二、问题描述 首先,掌握二叉树的各种存储结构和熟悉对二叉树的基本操作。其次,以二叉树表示算术表达式的基础上,设计一个十进制的四则运算的计算器。 如算术表达式:a+b*(c-d)-e/f 三、实验要求 如果利用完全二叉树的性质和二叉链表结构建立一棵二叉树,分别计算统计叶子结点的个数。求二叉树的深度。十进制的四则运算的计算器可以接收用户来自键盘的输入。由输入的表达式字符串动态生成算术表达式所对应的二叉树。自动完成求值运算和输出结果。四、实验环境 PC微机 DOS操作系统或 Windows 操作系统 Turbo C 程序集成环境或 Visual C++ 程序集成环境 五、实验步骤 1、根据二叉树的各种存储结构建立二叉树; 2、设计求叶子结点个数算法和树的深度算法; 3、根据表达式建立相应的二叉树,生成表达式树的模块; 4、根据表达式树,求出表达式值,生成求值模块; 5、程序运行效果,测试数据分析算法。 六、测试数据 1、输入数据:*(+)3 正确结果: 2、输入数据:(1+2)*3+(5+6*7); 正确输出:56 七、表达式求值 由于表达式求值算法较为复杂,所以单独列出来加以分析: 1、主要思路:由于操作数是任意的实数,所以必须将原始的中缀表达式中的操作数、操作符以及括号分解出来,并以字符串的形式保存;然后再将其转换为后缀表达式的顺序,后缀表达式可以很容易地利用堆栈计算出表达式的值。 例如有如下的中缀表达式: a+b-c 转换成后缀表达式为: ab+c- 然后分别按从左到右放入栈中,如果碰到操作符就从栈中弹出两个操作数进行运算,最后再将运算结果放入栈中,依次进行直到表达式结束。如上述的后缀表达式先将a 和b 放入栈中,然后碰到操作符“+”,则从栈中弹出a 和b 进行a+b 的运算,并将其结果d(假设为d)放入栈中,然后再将c 放入栈中,最后是操作符“-”,所以再弹出d和c 进行d-c 运算,并将其结果再次放入栈中,此时表达式结束,则栈中的元素值就是该表达式最后的运算结果。当然将原始的中缀表达式转换为后缀表达式比较关键,要同时考虑操作符的优先级以及对有括号的情况下的处理,相关内容会在算法具体实现中详细讨论。 2、求值过程 一、将原始的中缀表达式中的操作数、操作符以及括号按顺序分解出来,并以字符串的 形式保存。 二、将分解的中缀表达式转换为后缀表达式的形式,即调整各项字符串的顺序,并将括 号处理掉。 三、计算后缀表达式的值。 3、中缀表达式分解 DivideExpressionToItem()函数。分解出原始中缀表达式中的操作数、操作符以及括号,保存在队列中,以本实验中的数据为例,分解完成后队列中的保存顺序如下图所示: 数据结构二叉树基本操作 (1). // 对二叉树的基本操作的类模板封装 //------------------------------------------------------------------------------------------------------------------------ #include 《数据结构与数据库》 实验报告 实验题目 二叉树的基本操作及运算 一、需要分析 问题描述: 实现二叉树(包括二叉排序树)的建立,并实现先序、中序、后序和按层次遍历,计算叶子结点数、树的深度、树的宽度,求树的非空子孙结点个数、度为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,失败。 浙江大学城市学院实验报告 课程名称数据结构 实验项目名称实验十二叉树的基本操作 学生姓名专业班级学号 实验成绩指导老师(签名)日期 一.实验目的和要求 1、掌握二叉树的链式存储结构。 2、掌握在二叉链表上的二叉树操作的实现原理与方法。 3、进一步掌握递归算法的设计方法。 二.实验内容 1、按照下面二叉树二叉链表的存储表示,编写头文件binary_tree.h,实现二叉链表的定义与基本操作实现函数;编写主函数文件test10.cpp,验证头文件中各个操作。 二叉树二叉链表存储表示如下: typedef struct BiTNode { TElemType data ; struct BiTNode *lchild , *rchild ; }BiTNode,*BiTree ; 基本操作如下: ①void InitBiTree(BiTree &T ) //初始化二叉树T ②void CreateBiTree(BiTree &T) //按先序遍历序列建立二叉链表T ③bool BiTreeEmpty (BiTree T); //检查二叉树T是否为空,空返回1,否则返回0 ④int BiTreeDepth(BiTree T); //求二叉树T的深度并返回该值 ⑤void PreOrderTraverse (BiTree T); //先序遍历二叉树T ⑥void InOrderTraverse (BiTree T); //中序遍历二叉树T ⑦void PostOrderTraverse (BiTree T); //后序遍历二叉树T ⑧void DestroyBiTree(BiTree &T) //销毁二叉树T 重庆交通大学综合性设计性实验报告 班级:软件开发专业 2010级一班 实验项目名称:二叉树 实验项目性质:设计性实验 实验所属课程:数据结构 实验室(中心): 6教 指导教师:鲁云平 实验完成时间: 2012 年 4 月 29 日 一、实验目的 主要完成以下功能: 1. 建立二叉树 2. 计算结点所在的层次 3 .统计结点数量和叶结点数量 4. 计算二叉树的高度 5. 计算结点的度 6. 找结点的双亲和子女 7. 二叉树的遍历 8. 二叉树的输出等等 二、实验内容及要求 1.二叉树的结点结构,二叉树的存储结构由学生自由选择和设定 2.实验完成后上交打印的实验报告,报告内容与前面所给定的实验模板相同 3.将实验报告电子版和源代码在网络教学平台提交 三、实验设备及软件 Visual studio 2010 四、设计方案 ㈠题目(老师给定或学生自定) 二叉树的简单应用 ㈡设计的主要思路 通过递归原理实现大部分遍历二叉树功能 ㈢主要功能 1. 建立二叉树 2. 计算结点所在的层次 3 .统计结点数量和叶结点数量 4. 计算二叉树的高度 5. 计算结点的度 6. 找结点的双亲和子女 7. 二叉树的遍历 8. 二叉树的输出 五、主要代码 栈头文件:stack.h class Stack { public: Stack(int sz=100); ~Stack(){delete[]elements;} void Push(const T &x); bool Pop(T &x); bool getTop(T &x); bool IsEmpty()const{return(top==-1)?true:false;} bool IsFull()const{return(top==maxSize-1)?true:false;} private: T *elements; int top; 本程序由SOGOF完成 该完整程序主要是递归函数的使用及模板的使用,完成了对二叉树基本的链表操作,主要有二叉树的建立,前序、中序、后序遍历,求树的高度,每层结点数(包含树的最大宽度),左右结点对换,二叉树的内存释放,求解树的叶子数。 #include 二叉树的基本操作及实现 二叉树的基本操作及实现的代码如下: #include 实验3 树和二叉树 实验性质:验证性 实验学时:4学时 一、实验目的 1.掌握二叉树的特点、在计算机中的存储表示方法及其基本操作的实现; 2.能够利用二叉树求解一些常见问题。 二、实验预备知识 1.阅读并掌握二叉树二叉链表存储方法的类型定义及其创建、遍历等基本操作。 2.阅读并掌握赫夫曼树的创建、赫夫曼编码的求得等基本操作。 三、实验内容 1.理解并用二叉链表的操作运行下列程序: #include 创作编号: GB8878185555334563BT9125XW 创作者:凤呜大王* //二叉树的基本操作 #include cout<<"--------------请选择------------"< 题目: 编程实现二叉查找树的建立、中序遍历、元素查找等功能,要求解释实现过程及演示实际例子的运行结果。 算法描述: 首先创建二叉树结点类,其主要包括:二叉树结点数据域,指向左、右子树的指针,构造函数,设置当前结点左、右子树、数据域以及判断当前结点是否为叶子结点等。然后进行二叉树类定义,其私有部分为定义二叉树根结点指针,公有部分主要包括:构造函数、析构函数、判断二叉树是否为空树、先,中,后序遍历的递归与非递归、二叉树删除、层序遍历以及二叉树搜索等。接下来将对一些重要函数算法进行描述: 1、isLeaf函数:若该结点的左子树和右子树都为空,则为叶子结点。 2、isEmpty函数:根结点为空则为空树。 3、Parent函数:首先判断给定结点是否有双亲,根结点和空结点一定无双亲,初始化一个临时变量,用于跟进查找双亲结点,查找到后其保存的便是双亲结点。先递归在左子树中查找,如果找到,便结束递归且返回双亲结点指针;如果没有找到,再递归在右子树中查找。如果都没有找到,说明给定结点的双亲结点不在该二叉树中。 4、LeftSibling(RightSibling)函数:首先找到当前结点的双亲,然后判断双亲结点左右子树是否为空,其中必然有一个不为空,返回另一个子树指针即可。 5、DeleteBinaryTree函数:首先判断是否为空树,若为空,则返回,然后递归删除左子树,递归删除右子树,最后删除根结点。 6、PreOrder函数:首先判断是否为空树,若为空,则返回,然后访问根结点,递归遍历左子树,递归遍历右子树,结束。 7、PreOrderWithoutRecusion函数:使用栈来模拟递归过程,首先申请栈,用于保存结点指针序列,申请指针pointer保存当前根指针,然后判断栈是否为空,若栈为空且pointer为空,跳出函数,否则若pointer不为空,访问pointer所指结点,pointer入栈,pointer指向其左子树;若pointer为空,弹出栈顶元素赋给pointer,pointer指向其右子树,结束。 8、CreateTree函数:采用先序遍历序列构造二叉树,设‘0’为空结点,输入非‘0’数,生成新结点,递归创建左子树和右子树。 9、Search函数:采用先序遍历查找给定元素是否在二叉树中,首先判断树是否是空树,若是空树,则返回空指针。然后初始化临时指针temp,查找成功后temp即为所给元素所在 二叉树的创建与遍历 一、实验目的 1.学会实现二叉树结点结构和对二叉树的基本操作。 2.掌握对二叉树每种操作的具体实现,学会利用递归和非递归方法编写对二叉树这种递归数据结构进行处理的算法。 二、实验要求 1.认真阅读和掌握和本实验相关的教材内容。 2.编写完整程序完成下面的实验内容并上机运行。 3.整理并上交实验报告。 三、实验内容 1.编写程序任意输入二叉树的结点个数和结点值,构造一棵二叉树,采用三种递归和非递归遍历算法(前序、中序、后序)对这棵二叉树进行遍历。 四、实验步骤 源程序代码1 #include 实验五-二叉树基本操作的编程实现实验报告 ————————————————————————————————作者:————————————————————————————————日期: HUBEI UNIVERSITY OF AUTOMOTIVE TECHNOLOGY 数据结构 实验报告 这里一定填 写清楚自己 实验项目实验五实验类别基础篇 学生姓名朱忠栋学生学号20120231515 完成日期2014-12-16 指导教师付勇智 实验成绩评阅日期 评阅教师 实验五二叉树基本操作的编程实现 【实验目的】 内容:二叉树基本操作的编程实现 要求: 二叉树基本操作的编程实现(2学时,验证型),掌握二叉树的建立、遍历、插入、删除等基本操作的编程实现,也可以进一步编程实现查找等操作,存储结构主要采用顺序或链接结构。也鼓励学生利用基本操作进行一些应用的程序设计。 【实验性质】 验证性实验(学时数:2H) 【实验内容】 以下的选题都可以作为本次实验的推荐题目 1.建立二叉树,并以前序遍历的方式将结点内容输出。 2.将一个表示二叉树的数组结构转换成链表结构。 3.将表达式二叉树方式存入数组,以递归方式建立表达式之二叉树状结构,再分别输出前序、中序 及后序遍历结果,并计算出表达式之结果。 【注意事项】 1.开发语言:使用C。 2.可以自己增加其他功能。 【实验分析、说明过程】 页面不够,可续页。 根据自己选择的层次不同的实验内容,完善程序代码,调试通过后,分析说明该问题处理的详细算法过程。不需要写出详细的代码,只表达清楚详细的处理算法即可。可以采用流程图、形式语言或者其他数学表达方式来说明。 这次实验考查的主要是:递归建立二叉树,递归输出先序,中序和后序遍历的结果;非递归建立二叉树,再以非递归方式分别输出先序,中序和后序遍历的结果。 而对于基础篇考查的主要是:递归建立二叉树,递归输出先序,中序和后序遍历的结果,是以填空的方式进行考查的。 对于第一空:递归实现的先序遍历,其实现方法是: printf("%d",p->data); if(p->lchild!=NULL) preorder(p->lchild); if(p->rchild!=NULL) preorder(p->rchild); 对于第二空:递归实现的中序遍历,其实现方法是: if(p->lchild!=NULL) inorder(p->lchild); printf("%d",p->data); if(p->rchild!=NULL) inorder(p->rchild); 对于第三空:递归实现的后序遍历,其实现方法是: if(p->lchild!=NULL) postorder(p->lchild); if(p->rchild!=NULL) postorder(p->rchild); printf("%d",p->data); 【思考问题】 页面不够,可续页。 1.二叉树是树吗?它的定义为什么是递归的? 答:最多有两棵子树的有序树,称为二叉树。二叉树是一种特殊的树。具有n个结点的完全二叉树的深度为log2n +1 !!!二叉树的计算方法:若一棵二叉树为空,则其深度为0, 二叉树的基本操作实验报告 学号姓名实验日期 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, // (4)(D1,{H1})是一棵符合本定义的二叉树,称为根的左子树;(Dr,{Hr})是一棵符合本定义的二叉树,称为根的右子树。 //基本操作: CreateBiTree( &T, definition ) // 初始条件:definition给出二叉树T的定义。 // 操作结果:按definiton构造二叉树T。 BiTreeDepth( T ) // 初始条件:二叉树T存在。 // 操作结果:返回T的深度。 PreOrderTraverse( T, visit() ) // 初始条件:二叉树T存在,Visit是对结点操作的应用函数。 // 操作结果:先序遍历T,对每个结点调用函数Visit一次且仅一次。一旦visit()失败,则操 作失败。 InOrderTraverse( T, visit() ) // 初始条件:二叉树T存在,Visit是对结点操作的应用函数。 // 操作结果:中序遍历T,对每个结点调用函数Visit一次且仅一次。一旦visit()失败,则操 作失败。 PostOrderTraverse( T, visit() ) // 初始条件:二叉树T存在,Visit是对结点操作的应用函数。 // 操作结果:后序遍历T,对每个结点调用函数Visit一次且仅一次。一旦visit()失败,则操 作失败。 LeafNodes(p) // 初始条件:二叉树T存在。 // 操作结果:返回T的叶子结点数。 福建农林大学计算机与信息学院实验报告 树与二叉树 一、实验目的和要求 1)进一步掌握指针变量、动态变量的含义。 2)掌握二叉树的结构特性及各种存储结构的特点及适用范围。 3)掌握用指针类型描述、访问和处理二叉树的运算。 4)熟悉各种存储结构的特征及如何应用树结构解决具体问题。 二、实验内容和原理 实验内容: 编写程序实现交换二叉树中所有结点的左右子树的算法。 实验原理: 【问题描述】建立一棵二叉树,按层次遍历该二叉树,并实现将二叉树中所有结点的左右子树交换,显示其结果。 【基本要求】从键盘接受输入点(按层次遍历顺序),以“#”号结束,以二叉链表作为存储结构,将其二叉树中所有结点的左右子树交换,并将结果输出。 【实现】交换二叉树中所有结点的左右子树的具体步骤如下: ①将根结点进指针栈seqstack; ②当指针栈不空时,从栈顶取结点,如果此结点的左右孩子不为 空,则把其左右孩子交换,然后再分别将其左右孩子进栈; ③反复执行步骤②,直至指针栈为空时止。 三、实验环境 Windows XP系统 visual c++6.0 四、算法描述及实验步骤 #include "stdio.h" #include"stdlib.h" #define MAXSIZE 100 typedef char elemtype; typedef struct btnode {elemtype data; struct btnode *lchild, *rchild; }bitnode ,*bitree; typedef struct nodd {bitree addr; int parent; }sequre; bitree ins_node (bitree s,bitree t); void print_tree(bitree t); bitree creat_ordbt(); sequre seq[MAXSIZE]; void swap(bitree tree); int n=0; void main() {bitree tree; tree=creat_ordbt(); swap(tree); printf("输出交换后的二叉树\n"); print_tree(tree); } bitree creat_ordbt() {bitree t,s; elemtype x; t=NULL; printf("请按层次输入结点1的值(以#号结束,0号为空的结点):"); scanf("%c",&x); getchar(); while(x!='#') {n++; 郑州轻工业学院数据结构实验报告 题目 学生姓名 学号 专业班级 完成时间2016年月日 目录 一、系统功能介绍 (2) 二、需求分析 (2) 三、概要设计 (2) 四、详细设计 (5) 五、调试分析 (8) 六、使用说明 (8) 七、测试结果 (9) 八、心得体会 (10) 九、附录(程序代码) (11) 一、系统功能介绍 该系统主要功能是实现二叉树的定义和基本操作,包括定义二叉树的结构类型以及各个操作的具体函数的定义和主函数的定义。 各操作主要包括:初始化二叉树、按先序次序建立二叉树、检查二叉树是否为空、前序、中序、后序遍历树的方式、求树的深度、求树的结点数目、清空二叉树等九个对树的操作。 二、需求分析 本系统通过函数调用实现二叉树初始化,建立二叉树,检查树空与否,用前序、中序、后序遍历二叉树,求树的深度,求树的结点数目,清空二叉树等功能。 1)输出的形式和输出值的范围:在选择操作中,都以整型(数字)选择操作,插入和输出的数值都是char类型的字符; 2)输出的形式:在每次操作后,都会提示操作是否成功或者操作的结果; 3)程序达到的功能:完成初始化、检查是否为空、请空、遍历、求树的深度、求树的结点数目等功能; 4)测试数据设计: A,按先序次序建立二叉树。依次输入a,b,c,d,e,f,g.建立二叉树。 B,分别按先序,中序和后序遍历输出二叉树中的结点元素。 C,求树的高度和结点数。 三、概要分析 为了实现上述功能,定义二叉树的抽象数据类型。 ADT BinTree{ 数据对象D:D是具有相同特性的数据元素的集合。 数据关系R: 若D=¢,称BinTree为空二叉树 若D≠¢,则R={H},H是如下的二元关系; (1)在D中存在唯一的称为根的数据元素root,它在关系H下无前驱; (2)若D-{root}≠¢,则存在D-{root}={D1,Dr},且D1∩Dr=¢; (3)若D≠¢,则中存在唯一的元素x1,数据结构二叉树实验报告
实验三 二叉树的基本操作实现及其应用
二叉树的基本 操作
二叉树的基本操作实验
数据结构实验二叉树
数据结构——二叉树基本操作源代码
数据结构实验三——二叉树基本操作及运算实验报告
实验10 二叉树的基本操作
二叉树实验报告
二叉树基本操作经典实例
二叉树的基本操作及实现.cpp
实验3 树和二叉树
二叉树的基本 操作
二叉树实验报告
C++二叉树的创建与遍历实验报告
实验五-二叉树基本操作的编程实现实验分析报告
二叉树的基本操作实验报告
数据结构实验报告-树与二叉树
二叉树基本操作+数据结构+实验报告