二叉树及其应用
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验5:二叉树及其应用
一、实验目的
树是数据结构中应用极为广泛的非线性结构,本单元的实验达到熟悉二叉树的存储结构的特性,以及如何应用树结构解决具体问题。
二、问题描述
首先,掌握二叉树的各种存储结构和熟悉对二叉树的基本操作。
其次,以二叉树表示算术表达式的基础上,设计一个十进制的四则运算的计算器。
如算术表达式:a+b*(c-d)-e/f
三、实验要求
1、 如果利用完全二叉树的性质和二叉链表结构建立一棵二叉树,分别计算 a) 统计叶子结点的个数。
b) 求二叉树的深度。
2、 十进制的四则运算的计算器可以接收用户来自键盘的输入。
3、 由输入的表达式字符串动态生成算术表达式所对应的二叉树。
4、 自动完成求值运算和输出结果。
四、实验环境
PC 微机
DOS 操作系统或 Windows 操作系统
Turbo C 程序集成环境或 Visual C++ 程序集成环境
五、实验步骤
1、根据二叉树的各种存储结构建立二叉树;
2、设计求叶子结点个数算法和树的深度算法;
1、 根据表达式建立相应的二叉树,生成表达式树的模块; 4、根据表达式树,求出表达式值,生成求值模块; 1、 程序运行效果,测试数据分析算法。
-
+
/
a
*
b
-
e
f
C
d
六、测试数据
1、输入数据:2.2*(3.1+1.20)-7.5/3
正确结果:6.96
2、输入数据:(1+2)*3+(5+6*7);
正确输出:56
七、实验报告要求
实验报告应包括以下几个部分:
1、设计算术表达式树的存储结构;
2、给出二叉树中叶子结点个数算法和树的深度算法描述;
3、给出生成表达式树算法和求解算法描述;
4、相应的程序要给出足够的注释部分;
5、给出程序的测试结果;
6、实验总结。
八、思考题
1、分析利用完全二叉树的性质和二叉链表存储有什么不同?分析其优缺点。
2、增加输入表达式进行语法判错的功能。
实验源代码:
#include<stdio.h>
#include<iostream>
#include<malloc.h>
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define ERROR 0
#define NUMBER 1
#define SIMBLE 2
using namespace std;
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;// 栈
int InitStack( SqStack &s ){
s.base = (lpBiTreeNode *)malloc( STACK_INIT_SIZE*sizeof(lpBiTreeNode) );
if(!s.base)
return 0;
s.top = s.base;
s.stacksize = STACK_INIT_SIZE;
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;
s.top ++;
return 1;
}
int Pop( SqStack &s, lpBiTreeNode &e ){
if( s.top == s.base )
return 0;
s.top --;
e = *s.top;
return 1;
}
lpBiTreeNode GetTop( SqStack s ){
lpBiTreeNode e;
if( s.top == s.base )
return NULL;
e = *(s.top -1);
return e;
}
int IsEmpty( SqStack s ){
if( s.top == s.base )
return 1;
else
return 0;
}
int In( int c, int* op ){ // 判断c 是否在op 中,op为以结尾的数组while( *op != 0 ){
if( c == *op )
return 1;
op ++;
}
return 0;
}
int Precede( int theta1, int theta2 ){
int i, j;
int op_look[7][7] =
{ { '>', '>', '<', '<', '<', '>', '>' },
{ '>', '>', '<', '<', '<', '>', '>' },
{ '>', '>', '>', '>', '<', '>', '>' },
{ '>', '>', '>', '>', '<', '>', '>' },
{ '<', '<', '<', '<', '<', '=', ' ' },
{ '>', '>', '>', '>', ' ', '>', '>' },
{ '<', '<', '<', '<', '<', ' ', '=' }
};
switch( 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 ){
case'+':j = 0;
break;
case'-':j = 1;
break;
case'*':j = 2;
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' )
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;
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<IsFloat-1; 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<IsFloat-1; i++)
t*=10;
Result->Operand = result.Operand/(float)t;
return NUMBER;
}
}
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("输入算式");
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)
return NULL;
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);
LeafnumRchild = getLeafNum(Root->RChild);
return LeafnumLchild + LeafnumRchild;
}
}
return 0;
}
int getDepth(lpBiTreeNode Root){
int LeafDepthL;
int LeafDepthR;
if( Root != NULL ){
if(Root->LChild == NULL && Root->RChild == NULL)
return 0;
else{
LeafDepthL = getDepth(Root->LChild);
LeafDepthR = getDepth(Root->RChild);
return 1 + (LeafDepthL>LeafDepthR?LeafDepthL:LeafDepthR);
}
}
return 0;
}
void main(){
lpBiTreeNode Root;
float result;
if( Root = CreateBiTree() ){
printf( "叶子数: %d\n", getLeafNum(Root) );
printf( "深度: %d\n", getDepth(Root) );
if( calculate(Root, &result) ){
printf("Result: %0.2f\n", result);
}
else
printf("ERROR");
}
else
printf("INPUT ERROR\n");
system("pause");
}
实验截图。