表達式二叉樹順序存儲C++實現

表達式二叉樹順序存儲C++實現

表達式二叉樹

藉助二叉樹結構來存儲表達式,對於表達式二叉樹,根節點爲表達式中的運算符,子樹根節點也爲必然運算符,葉子節點必然爲運算數,在運算符中,括號優先級最大,加減符號次之,乘除符號最小。遞歸地建立表達式二叉樹,遇到括號則去掉,選擇高優先級的運算符,以該運算符爲子樹根節點,左右子表達式遞歸地建立左右子樹,直到遇到葉子節點。

int ExpressionBinaryTree::buildTree(const string& expression, int begin, int end) {
    int nodeNumber;
    int addSub = -1; 
    int mulDiv = -1;
    int parentheses = 0;
    if (end - begin == 1) {
    	// 若爲葉子節點
        nodeNumber = ++nodeCount;
        leftChild[nodeNumber] = rightChild[nodeNumber] = 0;
        nodes[nodeNumber] = expression[begin];
        return nodeNumber;
    }
    for (int i = begin; i < end; i++) {
        if (expression[i] == '(') {
            parentheses++;
        } else if (expression[i] == ')') {
            parentheses--;
        } else if ((expression[i] == '+' || expression[i] == '-') && parentheses == 0) {
        	// 若不存在括號,且存在加減號
            addSub = i;
        } else if ((expression[i] == '*' || expression[i] == '/') && parentheses == 0) {
        	// 若不存在括號和加減號,但存在乘除號
            mulDiv = i;
        }
    }
    
    int operatorNumber;
    if (addSub >= 0) {
    	// 若存在加減號,以加號或減號爲中心,左右兩邊的子表達式分別作爲左右子樹
        operatorNumber = addSub;
    } else if (mulDiv >= 0) {
    	// 若不存在加減號,但存在乘除號,以乘號或除號爲中心,左右兩邊的子表達式分別作爲左右子樹
        operatorNumber = mulDiv;
    } else {
    	// 若存在括號,去掉括號,繼續遞歸
        return buildTree(expression, begin + 1, end - 1);
    }
    nodeNumber = ++nodeCount;//增加新節點
    leftChild[nodeNumber] = buildTree(expression, begin, operatorNumber);//遞歸建立左子樹
    rightChild[nodeNumber] = buildTree(expression, operatorNumber + 1, end);//遞歸建立右子樹
    nodes[nodeNumber] = expression[operatorNumber];//將表達式中的值插入表達式二叉樹

    return nodeNumber;
}

實現代碼

/*
author : eclipse
email  : [email protected]
time   : Thu May 14 10:55:36 2020
*/
#include<bits/stdc++.h>
using namespace std;

class ExpressionBinaryTree {
private:
    static const int MAX_CAPACITY = 1024;
    int leftChild[MAX_CAPACITY];
    int rightChild[MAX_CAPACITY];
    char nodes[MAX_CAPACITY];
    int nodeCount;
    int root;
    string expression;
    int buildTree(const string& expression, int begin, int end);
    void inOrderTraverse(int p);
    void preOrderTraverse(int p);
    void postOrderTraverse(int p);
public:
    void preOrderSequence();
    void inOrderSequence();
    void postOrderSequence();
    ExpressionBinaryTree(string expression);
};


ExpressionBinaryTree::ExpressionBinaryTree(string expression) {
    this->expression = expression;
    nodeCount = 0;
    for (int i = 0; i < MAX_CAPACITY; i++) {
        leftChild[i] = rightChild[i] = 0;
        nodes[i] = 0;
    }
    root = buildTree(this->expression, 0, this->expression.length());
}

int ExpressionBinaryTree::buildTree(const string& expression, int begin, int end) {
    int nodeNumber;
    int addSub = -1; 
    int mulDiv = -1;
    int parentheses = 0;
    if (end - begin == 1) {
        nodeNumber = ++nodeCount;
        leftChild[nodeNumber] = rightChild[nodeNumber] = 0;
        nodes[nodeNumber] = expression[begin];
        return nodeNumber;
    }
    for (int i = begin; i < end; i++) {
        if (expression[i] == '(') {
            parentheses++;
        } else if (expression[i] == ')') {
            parentheses--;
        } else if ((expression[i] == '+' || expression[i] == '-') && parentheses == 0) {
            addSub = i;
        } else if ((expression[i] == '*' || expression[i] == '/') && parentheses == 0) {
            mulDiv = i;
        }
    }
    
    int operatorNumber;
    if (addSub >= 0) {
        operatorNumber = addSub;
    } else if (mulDiv >= 0) {
        operatorNumber = mulDiv;
    } else {
        return buildTree(expression, begin + 1, end - 1);
    }
    nodeNumber = ++nodeCount;
    leftChild[nodeNumber] = buildTree(expression, begin, operatorNumber);
    rightChild[nodeNumber] = buildTree(expression, operatorNumber + 1, end);
    nodes[nodeNumber] = expression[operatorNumber];

    return nodeNumber;
}

void ExpressionBinaryTree::preOrderTraverse(int p) {
    printf("%c", nodes[p]);
    if (leftChild[p]) {
        preOrderTraverse(leftChild[p]);
    }
    if (rightChild[p]) {
        preOrderTraverse(rightChild[p]);
    }
} 

void ExpressionBinaryTree::preOrderSequence() {
    preOrderTraverse(root);
}

void ExpressionBinaryTree::inOrderTraverse(int p) {
    if (leftChild[p]) {
        printf("(");
        inOrderTraverse(leftChild[p]);
    }
    printf("%c", nodes[p]);
    if (rightChild[p]) {
        inOrderTraverse(rightChild[p]);
        printf(")");
    }
}

void ExpressionBinaryTree::inOrderSequence() {
    inOrderTraverse(root);
}


void ExpressionBinaryTree::postOrderTraverse(int p) {
    if (leftChild[p]) {
        postOrderTraverse(leftChild[p]);
    }
    if (rightChild[p]) {
        postOrderTraverse(rightChild[p]);
    }
    printf("%c", nodes[p]);
} 

void ExpressionBinaryTree::postOrderSequence() {
    postOrderTraverse(root);
}

int main(int argc, char const *argv[])
{
    string expression;
    cin >> expression;
    ExpressionBinaryTree *expressionBinaryTree = new ExpressionBinaryTree(expression);
    printf("Pre order\n");
    expressionBinaryTree->preOrderSequence();
    printf("\nIn order\n");
    expressionBinaryTree->inOrderSequence();
    printf("\nPost order\n");
    expressionBinaryTree->postOrderSequence();
    return 0;
}

輸入數據

a*b-((c+d*e/f)+g)

輸出結果

Pre order
-*ab++c/*defg
In order
((a*b)-((c+((d*e)/f))+g))
Post order
ab*cde*f/+g+-

樣例圖解

鳴謝

《算法競賽入門經典》第二版

最後

  • 由於博主水平有限,不免有疏漏之處,歡迎讀者隨時批評指正,以免造成不必要的誤解!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章