在表达式树中插入节点

时间:2013-06-20 14:13:30

标签: c++ list expression-trees

我正在尝试使用二叉树来评估表达式。树有这个特点:

  • 每个节点都有零个,一个或两个孩子。
  • 仅包含运营商的节点可以有子节点。
  • 所有叶节点必须数字。
  • 为简单起见,唯一允许的运营商是*+

类似的那些:
Expression trees

这是我的树类:

class ExpressionTree {
    struct Node {
        std::string data;

        Node *leftChild, *rightChild;

        Node(std::string d): data(d), leftChild(NULL), rightChild(NULL) {}
    } *root;
    uint tsize;
public:
    ExpressionTree(): root(NULL), tsize(0) {}
    Node* treeRoot() { return root; }
    void insert(std::string s);
};

这是我的插入功能:

void insert(std::string s) {
    if (root == NULL) {
        root = new Node(s);
        ++tsize;
    } else {
        Node* current = root;
        while (true) {
            if (is_operator(current->data)) {
                if (current->leftChild == NULL) {
                    current->leftChild = new Node(s);
                    ++tsize;
                    return;
                } else if (current->rightChild == NULL) {
                    current->rightChild = new Node(s);
                    ++tsize;
                    return;
                } else {
                    if (is_operator(current->leftChild->data)) {
                        current = current->leftChild;
                        continue;
                    } else if (is_operator(current->rightChild->data)) {
                        current = current->rightChild;
                        continue;
                    } else {
                        std::cout << "Error: only nodes who hold operators"
                                  << " can have children." << std::endl;
                        return;
                    }
                }
            }
        }
    }
}

问题在于此功能。我从一个函数开始编写它,以便在二进制搜索树中插入节点,但它不起作用。当我运行一个简单的main(使用insert(),一次添加第二个树的节点)它崩溃而不返回任何错误,只有一个Windows 7对话框要求检查在线解决方案

我认为主要的问题是它不检查树的所有元素,而只检查一个分支,因此它以非法的方式附加新节点。不幸的是,我无法弄清楚如何解决这个问题。

我希望这个问题不是太具体。

注意:is_operator()需要一个字符串,如果true+则返回*,否则返回false。

2 个答案:

答案 0 :(得分:1)

我认为我发现了两个问题。

(A)

假设您尝试输入图片右侧的树。您已输入顶部的*以及下方的*+。您还输入了7121

现在您要输入12,这就是代码失败的地方。

root是一个运算符,两个子节点都不为null,所以你进入“else”子句并将左子节点视为当前位置。但这部分已经填满了!所以你将无法在那里插入任何东西。

不确定这是唯一的错误,因为您应该看到显示的错误消息。

(B)

我认为如果你从一个数字开始(不是运算符),你在尝试插入一个叶子时输入一个无限循环而你没有看到显示的信息(第一个如果总是失败的话)

答案 1 :(得分:1)

可以解决问题,为类添加为每个节点跟踪节点的跟踪的可能性。这里是新课程:

class ExpressionTree {
    struct Node {
    std::string data;

        Node *leftChild, *rightChild;
        Node* parent; // +

        Node(std::string d, Node* p):
        data(d), leftChild(NULL), rightChild(NULL), parent(p) {}
    } *root;
uint tsize;
public:
    ExpressionTree(): root(NULL), tsize(0) {}
    Node* treeRoot() { return root; }
    void insert(std::string s);
};

与前一个唯一的区别是添加了另一个Node*数据成员。这将把指针存储到父节点,这样就可以向后遍历树。

insert()函数也需要进行一些修改。这是:

void insert(std::string s) {
    if (root == NULL) {
        root = new Node(s, NULL);
        ++tsize;
    } else {
        Node* current = root;
        while (true) {
            if (is_operator(current->data)) {
                if (current->leftChild == NULL) {
                    current->leftChild = new Node(s, current);
                    ++tsize;
                    return;
                } else if (current->rightChild == NULL) {
                    current->rightChild = new Node(s, current);
                    ++tsize;
                    return;
                } else {
                    if (is_operator(current->leftChild->data)) {
                        current = current->leftChild;
                        continue;
                    } else if (is_operator(current->rightChild->data)) {
                        current = current->rightChild;
                        continue;
                    } else {
                        current = current->parent->rightChild; // +
                        continue;
                    }
                }
            } else {
                std::cout << "Error: only nodes who hold operators "
                          << "can have children." << std::endl;
                return;
            }
        }
    }
}

与以前版本的区别在于:在else内的主if中添加while语句,以便在所有叶节点都是数字的情况下打破循环(意味着他们不能生孩子) [1] 和前一个其他的替换(由// +指定),其中的分配是将光标转移到当前的父节点。

此外,构造函数Node()也会进行修改:每次创建一个新节点时,它都会与其父节点链接,并传递父节点指针ad第二个参数。

最后一件事。插入元素的顺序是自上而下左右。例如,在问题中的第一个树之后,必须按以下顺序插入元素:*, +, *, 7, 121, 12, +, 9, 3


Dr.Sam建议 [1]