简体   繁体   中英

List and count the most weight path from the root to the leafs of a binary tree

I have to return the number of nodes and the weight of the most weight path from the root to some leaf. Note that the tree is not a Binary Search Tree, is unsorted.

ie:

     6
   /   \
  9     6
 /     / \
3     1   19

Then, I have to return the integer 6 + 6 + 19 = 31 and print the node 6 - 6 - 19

So, this is my code:

int heavierPath ( Node * tree ) {
    if ( ! tree ) return 0;

    int leftWeight = heavierPath( tree->left );
    int rightWeight= heavierPath( tree->right );

    if ( leftWeight >= rightWeight ) {
        if ( tree->left )
            cout << tree->left->value << endl;
        return tree->value + leftWeight;
    }
    else {
        cout << tree->right->value << endl;

        return tree->value + rightWeight;
    }
};

And the result is 31 , but I see all the nodes values in the terminal.

How can I do to fix it and print only the elements that lies in the heavier path? (only recursive)

Thanks!

This appears to work after I edited it.

Take a look at: http://ideone.com/OGcyun as an example.

Your problem:

Consider the graph as:

     6
   /   \
  9     6
 /     / \
3     1   19

Number each node so:

     0
   /   \
  1     2
 /     / \
3     4   5

Consider the case where you are at node 1. You ask for the better path which gives you leftWeight = 3 and rightweight = 0 and you print the "better" path, 3. which isn't part of the end result.

The solution

To solve this problem, I passed up additional data up in a retstruct which contain the path (the heaviest path up to this point), value (to make printing easier), sum (to determine the better path).

Then I changed the function to:

retstruct* heavierPath ( Node * tree ) {
    if ( ! tree ) return new retstruct();

    //Get both paths
    retstruct* leftWeight = heavierPath( tree->left );
    retstruct* rightWeight= heavierPath( tree->right );

    //Find the "heavier" path
    if ( leftWeight->sum >= rightWeight->sum ) {
        //Delete lighter path
        delete_retstruct(rightWeight);
        //Pass up the better path with the correct data
        return new retstruct(leftWeight, tree->value, tree->value + leftWeight->sum);
    } else {
        //Delete lighter path
        delete_retstruct(leftWeight);
        //Pass up the better path with the correct data
        return new retstruct(rightWeight, tree->value, tree->value + rightWeight->sum);
    }
};

Added the delete_retstruct function:

void delete_retstruct (retstruct* path) {
    if (path->path == NULL) {
        delete path;
    } else {
        delete_retstruct(path->path);
    }
}

and the printPath function:

void printPath (retstruct* path) {
    if (path->path != NULL) {
        std::cout << " - " << path->value;
        printPath(path->path);
    }
}

This is used like so:

retstruct* path = heavierPath(tree);

//Print sum
std::cout << "Sum: " << path->sum << std::endl;

//Print path
std::cout << "Path: " << path->value;
printPath(path->path);
std::cout << std::endl;

Output:

Sum: 31
Path: 6 - 6 - 19

My suggestion is to make two functions,first function will find the leaf where path from root to it is maximum. So assuming you have pointer to such leaf here is the function to print the path.

bool print(struct node *r, struct node *leaf)
{

    if (r == NULL)
        return false;
    //will print if it is leaf or on path to leaf
    if (r == leaf || print(r->left, leaf) || print(r->right, leaf) )
    {
        printf("%d ", r->val); // this will print in reverse order
                               // if you want to print from root, store values in stack and then print the value after the function call
        return true;
    }

    return false;
}

The problem is that you are mixing printing the node with finding the sum. The later has to visit all child-nodes while printing only has to visit the ones in the path. Below is a possible solution:

#include <iostream>
#include <unordered_map>

struct Node
{
    Node(int value = 0, Node* left = nullptr, Node* right = nullptr) :
        value{value},
        left{left},
        right{right}
    {}

    int value;
    Node* left;
    Node* right;
};

std::unordered_map<Node*, int> map;

int pathSum(Node* node)
{
    if (node == nullptr)
    {
        return 0;
    }
    else if (map.find(node) == map.end())
    {
        return (pathSum(node->left) > pathSum(node->right)) 
                ? (map[node] = node->value + pathSum(node->left)) 
                : (map[node] = node->value + pathSum(node->right));
    }
    else
    {
        return map[node];
    }
}

void printPath(Node* node)
{
    if (node == nullptr)
    {
        return;
    }
    std::cout << node->value << std::endl;
    if (pathSum(node->left) > pathSum(node->right))
    {
        printPath(node->left);
    }
    else
    {
        printPath(node->right);
    }
}

int main() {

    Node* tree = new Node(6, 
                             new Node(9,
                                         new Node(3)),
                             new Node(6,
                                         new Node(1),
                                         new Node(19)));

    std::cout << "Biggest Sum: " << pathSum(tree) << std::endl;
    std::cout << "Biggest Sum Path: " << std::endl;
    printPath(tree);

    return 0;

}

In recursive solutions such as this, it's a good idea to cache the results hence the std::unordered_map. The code has been tested at Ideone .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM