I'm trying to construct a full binary tree (full meaning that every non leaf node has two leaf nodes connecting to it, i.e. node->right
and node->left
are != NULL
) given only the postorder traversal of the tree. In addition, I am given whether or not the node in the postorder traversal is a leaf node or not. The given postorder traversal looks like this:
2(1.000000e+00)
3(1.000000e+00)
(1.000000e+00 1.000000e+00)
1(1.000000e+00)
(1.000000e+00 2.000000e+00)
for example, where a line of the format "%d(%le)"
is a leaf node and "(%le %le)"
is a non-leaf node. Normally you can't construct a tree using only postorder because there would be multiple possibilities for connections, but I'm sure that being able to differentiate leaf vs. non-leaf nodes is important somehow. My current function looks like this:
Node *constructTreeHelper(FILE *infile, int *index) {
// Base case
if (*index <= 0) {
return NULL;
}
Node *root = NULL;
// Check for the "(" character
int check;
check = getc(infile);
fseek(infile, -1, SEEK_CUR);
// If the node is not a leaf node
if (check == 40) {
double lwire, rwire;
fscanf(infile, "(%le %le)\n", &lwire, &rwire);
root = createNode(0, 0, lwire, rwire);
*index = *index - 1;
if (*index >= 0) {
root->right = constructTreeHelper(infile, index);
root->left = constructTreeHelper(infile, index);
}
} else {
// If the node is a leaf node
int sink;
double cap;
fscanf(infile, "%d(%le)\n", &sink, &cap);
root = createNode(sink, cap, 0, 0);
*index = *index - 1;
if (*index >= 0) {
root->right = constructTreeHelper(infile, index);
root->left = constructTreeHelper(infile, index);
}
}
return root;
}
where index
is equal to the number of nodes in the tree - 1. Obviously, this implementation only builds nodes to the right. How can I update this to properly construct the tree?
Edit: Let me add some more information about what I know. So, the first node always has to be a leaf node, and the last node always has to be the root. Since this is not a binary search tree, but rather simply a binary tree, you cannot recursively call the function with updated range parameters each time. My implementation should solve it in O(n) time, but I just can't figure out how to make use of the knowledge in whether or not a node is a leaf node in constructing the tree.
There are some problems in your code:
you should use
ungetc()
instead offseek()
to backtrack by one character to avoid failure on streams that do not support seeking.you should write
(check == '(')
instead of hard coding the ASCII character value. It is both more portable and more readable.To avoid undefined behavior, you should check for
EOF
and forfscanf()
parsing success. As a matter of fact, this would avoid the need for the test oncheck
.When you parse a leaf node, you should not recurse and parse further nodes below the current one.
index
seems redundant as the sequence of nodes should suffice to full determine where to stop.
Here is a modified version:
Node *constructTreeHelper(FILE *infile, int *index) {
double lwire, rwire;
int sink;
double cap;
Node *node;
// Base case
if (*index <= 0) {
// This test seems redundant with the file contents */
return NULL;
}
// this fscanf will fail on the byte byte if it is not a '('
if (fscanf(infile, " (%le %le)", &lwire, &rwire) == 2) {
// If the node is not a leaf node
node = createNode(0, 0, lwire, rwire);
*index -= 1;
node->right = constructTreeHelper(infile, index);
node->left = constructTreeHelper(infile, index);
} else if (fscanf(infile, "%d(%le)\n", &sink, &cap) == 2) {
// If the node is a leaf node
node = createNode(sink, cap, 0, 0);
*index -= 1;
} else {
// invalid format or end of file */
node = NULL;
}
return node;
}
来源:https://stackoverflow.com/questions/54971981/constructing-full-binary-tree-given-only-postorder