问题
I'm trying to evaluate an expression using a binary tree. The tree has this characteristics:
- Each node has zero, one or two children.
- Only nodes containing operators can have children.
- All leaf nodes must be numbers.
- For the sake of simplicity, the only operators allowed are
*
and+
Something like those ones:
This is my tree class:
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);
};
And this is my insert function:
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;
}
}
}
}
}
}
The problem is in this function. I wrote it starting from a function to insert nodes in a Binary Search tree, but it doesn't work. When I run a simple main (that, using insert()
, adds the nodes of the second tree one at time) it crashes without returning any error, only a windows 7 dialog who asks to check for an online solution.
I think that the main problem is that it does not inspect all the elements of a tree, but only a branch, and for this reason it appends new nodes in an illegal way. Unfortunately, I can't figure out how to solve this.
I hope that this question is not too much specific.
Note: is_operator()
takes a string, and return true
if it's +
or *
, and false otherwise.
回答1:
I think that I spoted two problems.
(A)
Suppose that you try to enter the tree that is on the right in your picture. You already entered the *
on the top and the *
and +
below. You also entered the 7
and the 121
.
Now you want to enter the 12
and that's where your code fails.
The root is an operator and both children are not null, so you go in the "else" clause and consider the left child as the current location. BUT this part is already filled! So you will not be able to insert anything there.
Not sure however that it is the only error, since you should see your error message displayed.
(B)
I think that if you start with a number your tree (not with an operator), you enter an infinite loop when trying to insert a leaf and you do not see the message displayed (the first if always fails)
回答2:
The problem can be solved adding to the class the possibility to keep trace of the parent node for each node. Here the new class:
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);
};
The only difference from the previous one, is the addition of another Node*
data member. This will store the pointer to the parent node, giving in this way the possibility to traverse the tree backward.
Also the insert()
function needs some modifications. Here it is:
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;
}
}
}
}
The differences with the previous version are: the addition of an else
statement in the main if
inside the while
that breaks the loop in case that all leaf nodes are numbers (that means they cannot have children)[1] and the substitution (as specified by // +
) of the previous else with an assignment thats teps the cursor beckward to the parent node of the current one.
Moreover, also the constructor Node()
go through a modification: each time that a new node is created, it is linked with its parent passing the parent's pointer ad second argument.
Just a last thing. The order to insert elements is top-down left-right. For example, following the first tree in the question, the elements must be inserted in this order: *, +, *, 7, 121, 12, +, 9, 3
.
[1] suggested by Dr_Sam.
来源:https://stackoverflow.com/questions/17215944/insert-nodes-in-expression-trees