【数据结构学习笔记】——根据中缀表达式构建二叉树并输出

要求

输入一个中缀表达式,构造表达式树,以文本方式输出树结构。
输入:例如,输入a+b+c*(d+e)
输出:以缩进表示二叉树的层次,左(根),右(叶),上(右子树),下(左子树)
【数据结构学习笔记】——根据中缀表达式构建二叉树并输出_第1张图片

分析

我们有两个核心的问题需要解决,一是如何按照中缀表达式来构建二叉树,二是如何用这种形式进行输出。

放码过来

postfix.h

我们知道由后缀表达式生成二叉树很简单,所以我们需要做的第一步就是讲中缀表达式转换为后缀表达式。

中缀表达式转后缀表达式的方法:
1.遇到操作数:直接输出(添加到后缀表达式中)
2.栈为空时,遇到运算符,直接入栈
3.遇到左括号:将其入栈
4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈
6.最终将栈中的元素依次出栈,输出。

string postfix(string exp)
{
         char token;     //当前读取的字符 
         string s;
         Stack<char>opStack;
         string postfixExp;  //目标后缀表达式
         for(int i=0;i<exp.length();i++)
         {
                   token=(char)exp[i]; 
                   switch(token) 
                   {
                   case '(':
                            opStack.push(token); //是 ( 则放入栈中 
                            break;
                   case ')':
                            while(opStack.top()!='(') //将与之匹配的(之前的所有元素出栈 
                            {
                                     s=opStack.top();
                                     postfixExp.append(s);
                                     opStack.pop();
                            }
                            opStack.pop();
                            break;
                   case '+'://若栈为空 或 栈顶为( 或 当前为*/ 且栈顶为 +- (当前运算符优先级更高) 则直接入栈 
                   case '-':
                   case '*':
                   case '/':
                            if(opStack.empty()||opStack.top()=='('||(token=='*'||token=='/')&&(opStack.top()=='+'||opStack.top()=='-'))
                            {
                                     opStack.push(token);
                            }
                            else //若优先级低于栈顶元素  
                            {
                                     s=opStack.top();
                                     postfixExp.append(s);
                                     opStack.pop();
                                     if(opStack.top()=='+'||opStack.top()=='-')
                                     {
                                               s=opStack.top();
                                               postfixExp.append(s);
                                               opStack.pop();
                                     }
                                     opStack.push(token);
                            }
                            break;
                   default: //若为操作数则直接输出  
                                     s=token;
                                     postfixExp.append(s);
                                     break;
                   }
         }
         while(!opStack.empty())   //将栈中剩余的元素依次输出  
         {
                   s=opStack.top();
                   postfixExp.append(s);
                   opStack.pop();
         }
         return postfixExp;
};

binaryTree.h

后缀表达式生成二叉树(后缀表达式没有括号 )
1. 依次读取表达式;
2. 如果是操作数,则将该操作数压入栈中;
3. 如果是操作符,则弹出栈中的两个操作数,第一个弹出的操作数作为右孩子,
第二个弹出的操作数作为左孩子;然后再将该操作符压入栈中。

class Tnode
{
public:
         char value;
         Tnode *left,*right;
         Tnode(){}
         Tnode(const char value,Tnode *left=NULL,Tnode *right=NULL):value(value), left(left), right(right)
         {}
         Tnode* buildTree(string exp);//后缀表达式生成二叉树
         int depth(Tnode *root);//返回树高
         void print(Tnode *node_ptr, int depth);//转向打印二叉树(逆时针转90度打印)
        // void inorderOutput(Tnode *t);
};
 //后缀表达式生成二叉树
Tnode* Tnode::buildTree(string exp)
{
         Tnode *ptr;         
         StacknodeStack;
         char c;
         int i=0;
         c=exp[i++];
         while(c!='\0')
         {
                   if(c!='+' && c!='-' && c!='*' && c!='/')
                   {
                            ptr=new Tnode(c);
                            nodeStack.push(ptr);
                            c=exp[i++];
                   }
                   else
                   {
                            ptr=new Tnode(c);
                            if(!nodeStack.empty())
                            {
                                     ptr->right=nodeStack.top();
                                     nodeStack.pop();
                            }
                            if(!nodeStack.empty())
                            {
                                     ptr->left=nodeStack.top();
                                     nodeStack.pop();
                            }
                            nodeStack.push(ptr);
                            c=exp[i++];
                   }
         }
         return ptr;
}

//返回树高  
int Tnode::depth(Tnode *root)
{
         int i,j;
         if(root==NULL)
                   return 0;
         i=depth(root->left);
         j=depth(root->right);
         return i>j?i+1:j+1; 
}




void Tnode::print(Tnode *node_ptr, int depth)//逆时针90度打印二叉树(直接输出)
{ 
         if (node_ptr!= NULL)
    {
        print(node_ptr->right, depth+1);
        cout<3*depth)<<" ";
        cout<value<left,depth+1);
    }
}

说明:
一、在C++中,setw(int n)用来控制输出间隔。
例如:
cout<<’s’<< setw(8)<< ‘a’<< endl;
则在屏幕显示
s a
//s与a之间有7个空格,setw()只对其后面紧跟的输出产生作用,如上例中,表示’a’共占8个位置,不足的用空格填充。若输入的内容超过setw()设置的长度,则按实际长度输出。
setw()默认填充的内容为空格,可以setfill()配合使用设置其他字符填充。

cout<< setfill(‘*’)<< setw(5)<< ‘a’<< endl;
则输出:
****a //4个和字符a共占5个位置。

test.cpp

int main()
{
        // string infix="a+b+c*(d+e)";  //输入的中缀表达式  
         string infix;                  //自己输出任意表达式
         cout<<"请输入中缀表达式"<cin,infix);
         string s=postfix(infix); //s为输出化为的后缀表达式  
         cout<<"后缀表达式为:"<' ');
         Tnode *root;
         int high;
         root=tree.buildTree(s);
         high=tree.depth(root);
         tree.print(root,high);


}

结果

这里写图片描述
【数据结构学习笔记】——根据中缀表达式构建二叉树并输出_第2张图片

你可能感兴趣的:(数据结构)