1. 程式人生 > >【資料結構學習筆記】——根據中綴表示式構建二叉樹並輸出

【資料結構學習筆記】——根據中綴表示式構建二叉樹並輸出

要求

輸入一箇中綴表示式,構造表示式樹,以文字方式輸出樹結構。
輸入:例如,輸入a+b+c*(d+e)
輸出:以縮排表示二叉樹的層次,左(根),右(葉),上(右子樹),下(左子樹)
要求

分析

我們有兩個核心的問題需要解決,一是如何按照中綴表示式來構建二叉樹,二是如何用這種形式進行輸出。

放碼過來

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;         
         Stack<Tnode*>nodeStack;
         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<<setw(3*depth)<<" ";
        cout<<node_ptr->value<<endl;
        print(node_ptr->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<<"請輸入中綴表示式"<<endl;
         getline(cin,infix);
         string s=postfix(infix); //s為輸出化為的字尾表示式  
         cout<<"字尾表示式為:"<<s<<endl;
         Tnode tree(' ');
         Tnode *root;
         int high;
         root=tree.buildTree(s);
         high=tree.depth(root);
         tree.print(root,high);


}

結果

這裡寫圖片描述
這裡寫圖片描述