数据结构二叉树类型的实现.docx
- 文档编号:4439693
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:23
- 大小:23.88KB
数据结构二叉树类型的实现.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;i StackEmpty(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=='('
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 二叉 类型 实现