表达式二叉树.docx
《表达式二叉树.docx》由会员分享,可在线阅读,更多相关《表达式二叉树.docx(14页珍藏版)》请在冰豆网上搜索。
表达式二叉树
表达式二叉树
一、需求分析
1、对于任意给出的前缀表达式(不带括号)、中缀表达式(可以带括号)或后缀表达式(不带括号),能够在计算机内部构造出一棵表达式二叉树,并且图示出来(图形的形式)。
2、对于构造好的内部表达式二叉树,按照用户的要求输出相应的前缀表达式(不带括号)、中缀表达式(可以带括号,但不允许冗余括)或后缀表达式(不带括号)。
二、概要设计
1、ADT定义
classNode//节点类
{
public:
charoper;//数据域,为简便起见,操作数用单个字符代替
Node*left;//左孩子
Node*right;//右孩子
ints;intt;//计算树的层数使用
Node()
{left=right=NULL;
oper=0;
}
Node(charop)
{left=right=NULL;
oper=op;
}
};
boolisOper(charop)//判断是否为运算符
voidpostOrder(Node*p)//先序遍历
voidpreOrder(Node*p)//后序遍历
voidinOrder(Node*p)//中序遍历,同时输出不带冗余括号的中缀表达式
voidpost2tree(Node*&p,stringstr)//后缀表达式生成二叉树
voidpre2tree(Node*&p,stringstr)//前缀表达式生成二叉树
voidin2tree(Node*&p,stringstr)//中缀表达式转换成后缀表达式生成二叉树
voidpaint(Node*p)//打印树
voidcount(Node*p,int&height,intn)//求数的层数,以便与打印树
voidfreeTree(Node*&p)//递归删除树
intgetOperOrder(charop)//返回运算符op所对应的优先级
2、主程序和各模块的调用
intmain()
{
stringexpression;
Node*tree;
cout<<"前缀表达式-1中缀表达式0后缀表达式1"<intflag;
cin>>flag;
cout<<"请输入表达式:
"<cin>>expression;
if(flag==-1)//前缀表达式
pre2tree(tree,expression);
elseif(flag==1)//后缀表达式
post2tree(tree,expression);
else//中缀表达式
in2tree(tree,expression);
paint(tree);
cout<cout<<"前缀表达式为:
";
preOrder(tree);
cout<cout<<"中缀表达式为:
";
inOrder(tree);
cout<cout<<"后缀表达式为:
";
postOrder(tree);
cout<freeTree(tree);
cout<return0;
}
三、详细设计
1、表达式转化为二叉树
(1)前缀表达式:
从后往前扫描
①遇到操作数,把它赋给新建立的二叉树结点,入栈;
②遇到运算符,把它赋给新建立的二叉树的节点。
如果栈非空,从栈中弹出一个元素,把栈顶指针所指结点设为当前结点的左孩子,如果栈非空,再从栈中弹出一个元素,把栈顶指针所指结点设置为当前结点的右孩子,然后把当前节点压栈,最后一个元素就是二叉树的根结点。
(2)中缀表达式:
把中缀表达式转换成后缀表达式,然后再生成二叉树。
①定义一个运算符栈,并输入一个中缀表达式,然后从中缀表达式中自左至右依次读入各个字符。
②如果读入操作数,直接输出到后缀表达式。
③如果读入的是运算符,并且运算符栈为空,则将该运算符直接进栈;如果栈不为空,则
比较该运算符和栈顶运算符的优先级。
▪若该运算符高于栈顶运算符的优先级,则将该运算符直接进栈;
•若该运算符低于或等于栈顶运算符的优先级,则将栈中高于或等于该运算符优先级的元
素依次出栈输出到后缀表达式中,然后再将该运算符进栈。
④如果读入的是开括号“(”,则直接进栈;如果读入的是闭括号“)”,则一直出栈并输出到后缀表达式,直到遇到一个开括号“(”为止。
开括号“(”和闭括号“)”均不输出到后缀表达式。
⑤重复
(2)(3)(4)步,直到中缀表达式结束,然后将栈中剩余的所有运算符依次出栈。
(3)后缀表达式:
从前往后扫描
①碰到操作数则把它赋给相应的新建立的二叉树结点,若栈为空则入栈,
②碰到运算符则把它赋给相应的新建立的二叉树结点,若当前结点的左孩子为空则设为其左孩子,左孩子为满则设为其右孩子。
开始结点为根结点。
2、二叉树表达式转化为表达式
(1)前缀表达式:
对二叉树表达式进行前序遍历。
依次输出各结点。
(2)中缀表达式:
对二叉树表达式进行中序遍历。
如果当前结点的左子树是运算符,且运算符优先级低于当前运算符,那么左边的表达式要先计算,需要加括号,否则直接输出左子树;如果当前结点的右子树是运算符,且运算符优先级不高于当前运算符,那么右边的表达式要先计算,需要加括号,否则直接输出右子树。
依次输出各结点。
(3)后缀表达式:
对二叉树表达式进行后序遍历。
依次输出各结点。
四、程序测试
五、源程序
#include
#include
#include
#include
#include
usingnamespacestd;
classNode//结点类
{public:
charoper;
Node*left;
Node*right;
ints;intt;
Node()
{left=right=NULL;
oper=0;
}
Node(charop){left=right=NULL;
oper=op;
}
};
boolisOper(charop)//判断是否为运算符
{
charoper[]={'(',')','+','-','*','/','^'};
for(inti=0;i{if(op==oper[i])
{
returntrue;
}
}
returnfalse;
}
intgetOperOrder(charop)//返回运算符op所对应的优先级
{
switch(op){
case'(':
return1;
case'+':
case'-':
return2;
case'*':
case'/':
return3;
case'^':
return4;
default:
return0;
}
}
voidfreeTree(Node*&p)//递归删除树
{
if(p->left!
=NULL)
freeTree(p->left);
if(p->right!
=NULL)
freeTree(p->right);
delete(p);
}
voidpostOrder(Node*p)//先序遍历
{if(p)
{postOrder(p->left);
postOrder(p->right);
cout<oper;
}
}
voidpreOrder(Node*p)//后序遍历
{if(p)
{cout<oper;
preOrder(p->left);
preOrder(p->right);
}}
voidinOrder(Node*p)//中序遍历,同时输出不带冗余括号的中缀表达式
{if(p)
{
if(p->left)
{//如果当前节点的左子树是运算符,且运算符优先级低于当前运算符,
//那么左边的表达式要先计算,需要加括号
if(isOper(p->left->oper)&&getOperOrder(p->left->oper)oper))
{
cout<<"(";
inOrder(p->left);
cout<<")";
}
else//否则直接输出左子树
inOrder(p->left);
}
cout<oper;//输出当前节点
if(p->right)
{//如果当前节点的右子树是运算符,且运算符优先级不高于当前运算符,
//那么右边的表达式要先计算,需要加括号
if(isOper(p->right->oper)&&getOperOrder(p->right->oper)<=getOperOrder(p->oper))
{
cout<<"(";
inOrder(p->right);
cout<<")";
}
else
inOrder(p->right);
}
}
}
voidpost2tree(Node*&p,stringstr)//后缀表达式生成二叉树
{stacknodeStack;//用于保存节点指针的栈
chartemp;
inti=0;
temp=str[i++];
while(temp!
='\0')
{
if(temp!
='\0'&&!
isOper(temp))//不是运算符,则进栈
{
p=newNode(temp);//以temp为结点值构造二叉树结点
nodeStack.push(p);
temp=str[i++];//读入下一个
}
else
{//如果遇到符号,则出栈,依次设为右节点和左节点
p=newNode(temp);
if(nodeStack.size())
{
p->right=nodeStack.top();//若非空则出栈并设为结点的右孩子
nodeStack.pop();
}
if(nodeStack.size())
{
p->left=nodeStack.top();//若非空则出栈并设为结点的左孩子
nodeStack.pop();
}
nodeStack.push(p);
temp=str[i++];
}
}
}
voidpre2tree(Node*&p,stringstr)//前缀表达式生成二叉树
{
stacknodeStack;
chartemp;
inti=str.size()-1;
temp=str[i--];
while(temp!
='\0')
{
if(temp!
='\0'&&!
isOper(temp))
{p=newNode(temp);//以temp为内容来建立新的结点
nodeStack.push(p);
temp=str[i--];}
else
{p=newNode(temp);
if(nodeStack.size())//栈非空
{p->left=nodeStack.top();//则栈顶指针所指结点设置成当前结点左孩子
nodeStack.pop();
}
if(nodeStack.size())//栈非空
{p->right=nodeStack.top();//则栈顶指针所指结点设置成当前结点右孩子
nodeStack.pop();//栈顶元素左右孩子指针设置完毕弹出
}
nodeStack.push(p);
temp=str[i--];
}
}
}
voidin2tree(Node*&p,stringstr)//中缀表达式转换成后缀表达式生成二叉树
{
stacka;
chartemp;
stringPostfixexp="";
inti=0;
temp=str[i++];
while(temp!
='\0')
{
if(!
isOper(temp))//操作数则直接进数据栈
{Postfixexp+=temp;
temp=str[i++];
}
elseif(temp=='(')//进栈
{
a.push(temp);
temp=str[i++];
}
elseif(temp==')')
{
while(a.top()!
='(')//脱括号
{
Postfixexp+=a.top();
a.pop();//在碰到开括号和栈为空前反复弹出栈中元素
}
a.pop();
temp=str[i++];
}
elseif(temp=='+'||temp=='-'||temp=='*'||temp=='/')//出栈
{
while(!
a.empty()&&a.top()!
='('&&getOperOrder(a.top())>=getOperOrder(temp))
//若栈非空栈顶不是左括号且栈顶元素优先级不低于输入运算符时
{Postfixexp+=a.top();a.pop();}
a.push(temp);
temp=str[i++];
}
}//endwhile(temp!
='\0')
while(!
a.empty())
{Postfixexp+=a.top();
a.pop();
}
Postfixexp+='\0';
//cout<post2tree(p,Postfixexp);
}
voidcount(Node*p,int&height,intn){//求树的高度
if(p->left==NULL&&p->right==NULL)
{if(n>height)
height=n;}
if(p->left!
=NULL)
count(p->left,height,n+1);
if(p->right!
=NULL)
count(p->right,height,n+1);
}
voidpaint(Node*p)//打印树
{
intheight=0;
inth=0;
inti;
usingstd:
:
queue;
queueaQueue;
count(p,height,1);
Node*pointer=p;
Node*lastpointer;
if(pointer)
{pointer->s=1;
pointer->t=1;
aQueue.push(pointer);}
while(!
aQueue.empty())
{lastpointer=pointer;
pointer=aQueue.front();
aQueue.pop();
if(pointer->s>h)
{cout<h=pointer->s;}
if(pointer->t==1)
{for(i=0;is)-1;i++)
cout<<"";}
elseif(lastpointer->s!
=pointer->s){
for(i=0;i<(pointer->t-1)*(pow(2,height-pointer->s+1)-1)+(pointer->t-1)-1+pow(2,height-pointer->s);i++)
cout<<"";}
else
{for(i=0;i<(pointer->t-lastpointer->t)*(pow(2,height-pointer->s+1)-1)+(pointer->t-lastpointer->t)-1;i++)
cout<<"";}
cout<oper;
if(pointer->left!
=NULL){
pointer->left->s=pointer->s+1;
pointer->left->t=pointer->t*2-1;
aQueue.push(pointer->left);}
if(pointer->right!
=NULL){
pointer->right->s=pointer->s+1;
pointer->right->t=pointer->t*2;
aQueue.push(pointer->right);
}}}
intmain()
{
stringexpression;
Node*tree;
cout<<"前缀表达式-1中缀表达式0后缀表达式1"<intflag;
cin>>flag;
cout<<"请输入表达式:
"<cin>>expression;
if(flag==-1)//那么是前缀表达式
pre2tree(tree,expression);
elseif(flag==1)//那么是后缀表达式
post2tree(tree,expression);
else//否则中缀表达式
in2tree(tree,expression);
paint(tree);
cout<cout<<"前缀表达式为:
";
preOrder(tree);
cout<cout<<"中缀表达式为:
";
inOrder(tree);
cout<cout<<"后缀表达式为:
";
postOrder(tree);
cout<freeTree(tree);
cout<return0;
}