表达式二叉树.docx

上传人:b****4 文档编号:5066534 上传时间:2022-12-13 格式:DOCX 页数:14 大小:95.93KB
下载 相关 举报
表达式二叉树.docx_第1页
第1页 / 共14页
表达式二叉树.docx_第2页
第2页 / 共14页
表达式二叉树.docx_第3页
第3页 / 共14页
表达式二叉树.docx_第4页
第4页 / 共14页
表达式二叉树.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

表达式二叉树.docx

《表达式二叉树.docx》由会员分享,可在线阅读,更多相关《表达式二叉树.docx(14页珍藏版)》请在冰豆网上搜索。

表达式二叉树.docx

表达式二叉树

表达式二叉树

一、需求分析

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;

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1