2

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.

1 Answer 1

2

There are some problems in your code:

  • you should use ungetc() instead of fseek() 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 for fscanf() parsing success. As a matter of fact, this would avoid the need for the test on check.

  • 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;
} 
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for the corrections. Your tip on not calling the function again when parsing a leaf node makes a lot of sense. I need to find a way to rewrite my function so it can continue once it parses a leaf node.
Look at the code I just posted, and try and remove the index variable. You could extend the syntax for a more generic parser that would recognize null for incomplete trees.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.