数据结构二叉树类型的实现.docx
《数据结构二叉树类型的实现.docx》由会员分享,可在线阅读,更多相关《数据结构二叉树类型的实现.docx(23页珍藏版)》请在冰豆网上搜索。
数据结构二叉树类型的实现
实验4表达式二叉树类型的实现
源代码及每步注解:
文件expression.h
/*头文件以及存储结构*/
#include
#include
#include
#include
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineOVERFLOW0
typedefintStatus;
/*二叉树结点类型*/
typedefenum{INT,CHAR}ElemTag;/*INT为整型数据num,CHAR为字符型数据c*/
typedefstructTElemType
{
ElemTagtag;/*{INT,CHAR}指示是整型还是字符型*/
union
{
intnum;/*tag=INT时,为整型*/
charc;/*tag=CHAR时,为字符型*/
};
}TElemType;
/*二叉树的二叉链表存储表示*/
typedefstructBiTNode
{
TElemTypedata;
structBiTNode*lchild,*rchild;/*左右孩子指针*/
}BiTNode,*BiTree;
typedefBiTreeSElemType;/*栈SqStack的元素*/
typedefcharSElemType1;/*栈SqStack1的元素*/
/*栈的顺序存储表示*/
#defineSTACK_INIT_SIZE10/*存储空间初始分配量*/
#defineSTACKINCREMENT2/*存储空间分配增量*/
/*两个顺序栈*/
typedefstructSqStack
{
SElemType*base;/*在栈构造之前和销毁之后,base的值为NULL*/
SElemType*top;/*栈顶指针*/
intstacksize;/*当前已分配的存储空间,以元素为单位*/
}SqStack;/*顺序栈*/
typedefstructSqStack1
{
SElemType1*base;/*在栈构造之前和销毁之后,base的值为NULL*/
SElemType1*top;/*栈顶指针*/
intstacksize;/*当前已分配的存储空间,以元素为单位*/
}SqStack1;/*顺序栈*/
/*顺序栈的基本操作*/
StatusInitStack(SqStack*S)
{/*构造一个空栈S*/
(*S).base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!
(*S).base)
exit(OVERFLOW);/*存储分配失败*/
(*S).top=(*S).base;
(*S).stacksize=STACK_INIT_SIZE;
returnOK;
}
StatusStackEmpty(SqStackS)
{/*若栈S为空栈,则返回TRUE,否则返回FALSE*/
if(S.top==S.base)returnTRUE;
elsereturnFALSE;
}
StatusPush(SqStack*S,SElemTypee)
{/*插入元素e为新的栈顶元素*/
if((*S).top-(*S).base>=(*S).stacksize)/*栈满,追加存储空间*/
{
(*S).base=(SElemType*)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(SElemType));
if(!
(*S).base)exit(OVERFLOW);/*存储分配失败*/
(*S).top=(*S).base+(*S).stacksize;
(*S).stacksize+=STACKINCREMENT;
}
*((*S).top)++=e;
returnOK;
}
StatusPop(SqStack*S,SElemType*e)
{/*若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR*/
if((*S).top==(*S).base)returnERROR;
*e=*--(*S).top;
returnOK;
}
StatusGetTop(SqStackS,SElemType*e)
{/*若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR*/
if(S.top>S.base)
{
*e=*(S.top-1);
returnOK;
}
else
returnERROR;
}
/*顺序栈的基本操作*/
StatusInitStack1(SqStack1*S)
{/*构造一个空栈S*/
(*S).base=(SElemType1*)malloc(STACK_INIT_SIZE*sizeof(SElemType1));
if(!
(*S).base)
exit(OVERFLOW);/*存储分配失败*/
(*S).top=(*S).base;
(*S).stacksize=STACK_INIT_SIZE;
returnOK;
}
StatusStackEmpty1(SqStack1S)
{/*若栈S为空栈,则返回TRUE,否则返回FALSE*/
if(S.top==S.base)returnTRUE;
elsereturnFALSE;
}
StatusPush1(SqStack1*S,SElemType1e)
{/*插入元素e为新的栈顶元素*/
if((*S).top-(*S).base>=(*S).stacksize)/*栈满,追加存储空间*/
{
(*S).base=(SElemType1*)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(SElemType1));
if(!
(*S).base)exit(OVERFLOW);/*存储分配失败*/
(*S).top=(*S).base+(*S).stacksize;
(*S).stacksize+=STACKINCREMENT;
}
*((*S).top)++=e;
returnOK;
}
StatusPop1(SqStack1*S,SElemType1*e)
{/*若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR*/
if((*S).top==(*S).base)returnERROR;
*e=*--(*S).top;
returnOK;
}
StatusGetTop1(SqStack1S,SElemType1*e)
{/*若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR*/
if(S.top>S.base)
{
*e=*(S.top-1);
returnOK;
}
else
returnERROR;
}
文件expression.cpp
#include"expression.h"
/*全局变量*/
intsave_number[31];/*在按原表达式输入形式中,输入的常量保存到数组save_number中,常量最多为30个,0单元不用*/
charExpr_String[30];/*存放表达式的字符串*/
/*以字符序列的形式输入语法正确的前缀表达式,保存到字符串string*/
/*参数flag=0表示输出的提示信息是"请输入正确的前缀表示式:
"*/
/*flag=1表示输出的提示信息为"请以表达式的原书写形式输入正确表示式:
"*/
StatusInput_Expr(char*string,intflag)
{
if(flag==0)printf("\n请输入正确的前缀表示式:
");
elseprintf("\n请以表达式的原书写形式输入正确表示式:
");
flushall();/*清理缓冲区*/
gets(string);/*从键盘输入一串字符串作为表达式*/
if(strlen(string)==1)/*输入的表达式字符串长度为1*/
if(string[0]=='+'||string[0]=='-'||string[0]=='*'||string[0]=='/'||string[0]=='^')/*输入的表达式只有一个运算符*/
{printf("\n表达式只有一个字符,为运算符,错误!
");returnERROR;}
elseif((string[0]>='0'&&string[0]<'9')||(string[0]>='a'&&string[0]<='z')||(string[0]>='A'&&string[0]<='Z'))
/*输入的表达式只有一个数字或字符*/
{printf("\n表达式只有一个字符!
");returnOK;}
else{printf("\n输入的字符不是运算符也不是变量常量,错误!
");returnERROR;}
returnOK;
}
/*判断字符string[i],如果是'0'-'9'常量之间,二叉树结点存为整型;否则,存为字符型*/
voidjudge_value(BiTree*E,char*string,inti)
{
if(string[i]>='0'&&string[i]<='9')/*为常量*/
{(*E)->data.tag=INT;(*E)->data.num=string[i]-48;}
elseif(string[i]>=1&&string[i]<=20)/*为常量,常量存于数组save_number中*/
{(*E)->data.tag=INT;(*E)->data.num=save_number[string[i]];}
else/*为变量*/
{(*E)->data.tag=CHAR;(*E)->data.c=string[i];}
}
/*以正确的前缀表示式并构造表达式E*/
StatusReadExpr(BiTree*E,char*exprstring)
{
SqStackS;
inti,len;/*len为表达式的长度*/
BiTreep,q;
(*E)=(BiTree)malloc(sizeof(BiTNode));/*申请二叉树的根结点的空间*/
(*E)->lchild=NULL;
(*E)->rchild=NULL;
len=strlen(exprstring);/*len赋值为表达式的长度*/
if(len==1)/*表达式长度为1时,二叉树只有根结点*/
judge_value(E,exprstring,0);/*将exprstring[0]存入二叉树的结点中*/
else
{
judge_value(E,exprstring,0);/*将exprstring[0]存入二叉树的结点中*/
InitStack(&S);/*初始化栈*/
q=(*E);
Push(&S,q);/*入栈*/
Push(&S,q);/*入栈,根结点入栈两次是为判断先序输入的表达式是不是正确的表达式*/
for(i=1;iStackEmpty(S);i++)
{
p=(BiTree)malloc(sizeof(BiTNode));
judge_value(&p,exprstring,i);/*将exprstring[i]存入二叉树的结点中*/
p->lchild=NULL;
p->rchild=NULL;
if(exprstring[i]=='+'||exprstring[i]=='-'||exprstring[i]=='*'||exprstring[i]=='/'||exprstring[i]=='^')
{/*为运算符,运算符入栈,左孩子不空,向左孩子走,否则,如果右孩子不空,向右孩子走*/
if(!
q->lchild){q->lchild=p;Push(&S,p);q=p;}
else{q->rchild=p;Push(&S,p);q=p;}
}
else/*不是运算符,运算符出栈*/
{
if(!
q->lchild){q->lchild=p;Pop(&S,&q);}
else{q->rchild=p;Pop(&S,&q);}
}
}
if(StackEmpty(S)&&i>=len)returnOK;/*栈空且i>=len,说明输入的表达式是正确的*/
else/*输入的表达式是错误的*/
{
printf("\n输入的表达式有误!
");
returnERROR;
}
}
}
/*如果两个字符是运算符,比较两个运算符的优先级,c1比c2优先,返回OK,否则返回ERROR*/
StatusPri_Compare(charc1,charc2)
{
if((c1=='^'||c1=='*'||c1=='-'||c1=='+'||c1=='/')&&(c2=='^'||c2=='*'||c2=='-'||c2=='+'||c2=='/'))
{/*c1和c2为运算符*/
if(c1=='^')/*c1为指数运算符,则当c2不为'^'时,c1比c2优先*/
{
if(c2!
='^')returnOK;
elsereturnERROR;
}
elseif(c1=='*'||c1=='/')/*c1为乘法或除法运算符,则当c2为'+'或'-',c1比c2优先*/
{
if(c2=='^'||c2=='*'||c2=='/')returnERROR;
elsereturnOK;
}
elsereturnERROR;/*其余,c1不比c2优先*/
}
elsereturnERROR;/*c1和c2不是运算符*/
}
/*用带括弧的中缀表达式输入表达式*/
voidWriteExpr(BiTreeE)
{
if(E)/*树不为空*/
{/*先递归左子树*/
if(E->lchild&&E->lchild->data.tag==CHAR)/*E的左孩子不为空,且左孩子为字符*/
{
if(Pri_Compare(E->data.c,E->lchild->data.c))/*E->data.c比E->lchild->data.c优先*/
{printf("(");WriteExpr(E->lchild);printf(")");}/*带括弧输出左子树*/
elseWriteExpr(E->lchild);/*否则,不带括弧输出左子树*/
}
elseWriteExpr(E->lchild);/*否则,输出左子树*/
/*访问输出根结点的值*/
if(E->data.tag==INT){printf("%d",E->data.num);}
elseprintf("%c",E->data.c);
/*后递归右子树*/
if(E->rchild&&E->rchild->data.tag==CHAR)/*E的右孩子不为空,且右孩子为字符*/
{
if(Pri_Compare(E->data.c,E->rchild->data.c))/*E->data.c比E->rchild->data.c优先*/
{printf("(");WriteExpr(E->rchild);printf(")");}/*带括弧输出右子树*/
elseWriteExpr(E->rchild);/*否则,不带括弧输出右子树*/
}
elseWriteExpr(E->rchild);/*否则,输出右子树*/
}
}
/*实现对表达式中的所有变量V的赋值(V=c),参数flag为表示是否赋值过的标志*/
voidAssign(BiTree*E,charV,intc,int*flag)
{
if(*E)
{
if((*E)->data.tag==CHAR&&(*E)->data.c==V)/*如果找到要赋值的变量,赋值*/
{(*E)->data.tag=INT;(*E)->data.num=c;*flag=1;}
Assign(&((*E)->lchild),V,c,flag);/*递归左子树*/
Assign(&((*E)->rchild),V,c,flag);/*递归左子树*/
}
}
/*指数运算函数,底数为x,指数为exp*/
longpower(intx,intexp)
{
longresult;
inti;
for(i=1,result=1;i<=exp;i++)
result*=x;
returnresult;
}
/*运算符运算求值,参数opr1,opr2为常量,opr为运算符,根据不同的运算符,实现不同的运算,返回运算结果*/
longOperate(intopr1,charopr,intopr2)
{
longresult;
switch(opr)
{
case'+':
/*加法*/
result=opr1+opr2;
returnresult;break;
case'-':
/*减法*/
result=opr1-opr2;
returnresult;break;
case'*':
/*乘法*/
result=opr1*opr2;
returnresult;break;
case'/':
/*除法,除法是在整型类型上的除法*/
result=opr1/opr2;
returnresult;break;
case'^':
/*指数运算*/
result=power(opr1,opr2);
returnresult;break;
default:
break;
}
}
/*检查表达式是否还存在没有赋值的变量,以便求算数表达式的值*/
StatusCheck(BiTreeE)
{
if(E&&E->data.tag==CHAR)/*树不为空*/
{
if(E->data.c!
='*'&&E->data.c!
='^'&&E->data.c!
='-'&&E->data.c!
='+'&&E->data.c!
='/')
{printf("\n表达式中仍存在变量没有赋值!
没法求出表达式的值!
");returnERROR;}
/*存在变量,提示信息,后返回ERROR*/
if(Check(E->lchild))/*递归左子树*/
Check(E->rchild);/*递归右子树*/
}
}
/*对算术表达式求值*/
longValue(BiTreeE)
{
if(E)/*树不为空*/
{
if(!
E->lchild&&!
E->rchild&&E->data.tag==INT)return(E->data.num);
/*结点的左孩子和右孩子为空,为叶子结点,返回结点的值*/
returnOperate(Value(E->lchild),E->data.c,Value(E->rchild));
/*运算求值,后根遍历的次序对表达式求值,其中参数递归调用了Value()函数求左子树的值和右子树的值*/
}
}
/*构造一个新的复合表达式*/
voidCompoundExpr(charP,BiTree*E1,BiTreeE2)
{
BiTreeE;
E=(BiTree)malloc(sizeof(BiTNode));/*申请一个结点存放运算符P*/
E->data.tag=CHAR;
E->data.c=P;/*申请到的结点值为P*/
E->lchild=(*E1);/*结点的左孩子为E1*/
E->rchild=E2;/*结点的右孩子为E2*/
(*E1)=E;/*(*E1)为根结点*/
printf("\n表达式E复合成功!
其表达式变为:
\n");
WriteExpr(E);/*输出复合好的表达式*/
}
/*以表达式的原书写形式输入,表达式的原书写形式字符串string变为字符串pre_expr*/
/*后调用reversal_string()函数反转得到前缀表达式pre_expr*/
StatusRead_Inorder_Expr(char*string,char*pre_expr)
{
inti,j,len,char_number=1;/*len表示字符串string的长度,char_number是记录数组save_number[]的个数*/
intnumber;/*保存大于9的常量*/
charc,c1;
SqStack1S;/*栈定义*/
InitStack1(&S);/*初始栈*/
Push1(&S,'#');/*先将字符'#'入栈,用来表示作为栈的最底一个元素*/
len=strlen(string);/*len为字符串string的长度*/
c=string[len-1];/*从字符串的最后一个字符开始向前扫描*/
i=len-1;
while(!
StackEmpty1(S)&&i>=0)/*栈不为空且i大于等于0*/
{
if(c=='('