表达式二叉树顺序存储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  : eclipsecs@qq.com
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+-

样例图解

鸣谢

《算法竞赛入门经典》第二版

最后

  • 由于博主水平有限,不免有疏漏之处,欢迎读者随时批评指正,以免造成不必要的误解!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值