简体   繁体   中英

Copy leafs from a Binary Search Tree (Recursively), in C++

I am trying to copy leafs (recursively) from a BST to a new BST that include the copied leafs only. Here is what I did:

27 void tree::copy_leafs(node * src, node *& dst) {
28     if (!src)                                 //Case 1: current node is NULL
29         return;
30     if (!src->left && !src->right) {          //Case 2: current node is a leaf
31         dst = new node;
32         dst->data = src->data;
33         dst->left = NULL;
34         dst->right = NULL;
35         copy_leafs(src->left, dst->left);
36         copy_leafs(src->right, dst->right);
37     } else {                                  //Case 3: current node is NOT a leaf
38         copy_leafs(src->left, dst);
39         copy_leafs(src->right, dst);
40    }
41 }

The code seems to be right when it comes to compiling, visiting leafs and copying them. However, the root of the new tree ( dst ) always has one leaf only (the last leaf). Any ideas?

EX of the problem:

  • Say that src had these leafs: 4 15 19 23
  • After this function, dst will only have 23 .

Since the bug has already been found in the comments, here's a very superficially tested solution.

You can't blindly copy nodes; you need to create a BST structure.
You can do this by first copying the leaves to the left and the leaves to the right and then joining them in a suitable way.

Since you start with a BST, the greatest node in the left copy is smaller than the smallest node in the right copy.
This means that you will get a BST if you replace the leftmost left-pointer (which is null) in the right copy with the root of the left copy.

This may lead to a very unbalanced tree, of course.
If you want to balance it, you need a more sophisticated solution, which is left as an exercise.

Assuming this node structure:

struct node
{
    int datum;
    node* left;
    node* right;
    node(int v) : datum(v), left(nullptr), right(nullptr) {}
};

it would look something like this:

node* copy_leaves(const node* tree)
{
    if (!tree)
    {
        return nullptr;
    }
    if (!tree->left && !tree->right)
    {
        return new node(tree->datum);
    }

    // Not a leaf; recurse
    node* left_leaves = copy_leaves(tree->left);
    node* right_leaves = copy_leaves(tree->right);
    if (!left_leaves)
    {
        return right_leaves;
    }
    else if (!right_leaves)
    {
        return left_leaves;
    }
    else
    {
        // Locate the leftmost node in the right tree.
        node* smallest_right = right_leaves;
        while (smallest_right->left != nullptr)
        {
            smallest_right = smallest_right->left;
        }
        // And attach the left leaf tree.
        smallest_right->left = left_leaves;
        return right_leaves;
    }
}

I believe it's possible to make copy_leaves also give you the leftmost node, which saves some top-down traversals, but it complicates the code so I'm leaving that as an exercise.

void copy_leaves(node * src, node *& dest)
{
    if (!src) return;

    dest = new node(src->data); // this should zero out the pointers, assuming you make one.

    copy_leaves(src->left, dest->left);
    copy_leaves(src->right, dest->right);
}

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