树结构 - 不正确的孩子

时间:2015-05-15 18:32:50

标签: c++ tree

我试图在C ++中构建简单的结构。它应该类似于AVL树。

当我在main()函数中构建一个包含三个节点的简单树时,一切正常。

问题是当我尝试使用insert()函数时。该函数的第一个参数包含从第二个参数中放入值的信息。

以下是代码:

#include <numeric>
#include <vector>
#include <cstdio>
#include <cstdlib>
using namespace std;

struct Node {
    Node* left;
    Node* right;
    Node* parent;
    int value;
    int count_leafs;
    int height;
};

Node* root;


void insert2(int p, int value, Node* node, int left) 
{
    //printf("insert %d %d - (%d, %d) %d \n", p, value, node->left, node->right, left);

    if (root == NULL) {
        //  creating a tree root

        Node new_node;
        new_node.left = NULL;
        new_node.right = NULL;
        new_node.parent = NULL;

        root = &new_node;

        root->value = value;
        root->count_leafs = 1;
        root->height = 1;
        return;
    }

    if (node->left == NULL && node->right == NULL) {
        //  joining value to the leaf

        Node new_parent;
        new_parent.count_leafs = 2;
        new_parent.height = 2;
        new_parent.value = node->value + value;
        new_parent.parent = node->parent;
        new_parent.left = NULL;
        new_parent.right = NULL;

        Node new_leaf;
        new_leaf.value = value;
        new_leaf.count_leafs = 1;
        new_leaf.left = NULL;
        new_leaf.right = NULL;
        new_leaf.height = 1;
        new_leaf.parent = &new_parent;

        new_parent.left = &new_leaf;
        new_parent.right = node;


        if (node->parent != NULL && node->parent->left != NULL && node->parent->left == node) {
            printf("a");
            node->parent->left = &new_parent;
        }

        if (node->parent != NULL && node->parent->right != NULL && node->parent->right == node) {
            printf("b");
            node->parent->right = &new_parent;  
        }

        node->parent = &new_parent;

        return;
    }

    //printf("GOTO: %d %d \n", left + node->left->count_leafs, p);

    node->value += value;
    node->count_leafs += 1;

    if (left + node->left->count_leafs + 1 >= p) {
        //printf("W left\n");
        insert2(p, value, node->left, left);
    } else {    
        //printf("W right\n");
        insert2(p, value, node->right, left + node->left->count_leafs);
    }
}


void insert(int p, int value) 
{
    insert2(p, value, root, 0);
}

int main() 
{
    Node new_root;
    root = NULL;

    new_root.value = 10;
    new_root.height = 2;
    new_root.count_leafs = 2;
    new_root.parent = NULL;
    root = &new_root;

    Node left;
    left.value = 6;
    left.height = 1;
    left.count_leafs = 1;
    left.parent = root;
    left.left = NULL;
    left.right = NULL;

    Node right;
    right.value = 4;
    right.height = 1;
    right.count_leafs = 1;
    right.parent = root;
    right.left = NULL;
    right.right = NULL;

    root->left = &left;
    root->right = &right;

    // PLACE A

    insert(0, 1);

    // PLACE B

    return 0;
}

如前所述,PLACE A正在构建一个包含3个节点的树。在地方A中看起来像这样:

  10
 /  \
6    4

接下来,在PLACE A和PLACE B之间的一行中,我想添加一个新节点。之后(在PLACE B中)树应该如下所示:

    11
   /  \
  7    4
 / \
1   6

但我得到这样的东西:

            11
           /  \
  1972250912   4
     / \
    2   2

我无法弄清楚出了什么问题。它应该是insert2()函数中的问题,但我无法找到它。

你看到了吗? 在此先感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

此类行为的原因是您使用范围变量超出范围。您不得使用指向该范围之外的范围变量的指针。范围变量仅在声明范围时存在。如果决定从范围外访问范围变量,您将访问某些堆栈,这些堆栈会覆盖该变量,导致未定义的行为。

我的意思是,你不能这样做:

if (root == NULL) 
{
    Node new_node;
    root = &new_node;
    return;
}

您可以使用运算符 new 在堆中创建struct Node 的新实例,并在以后使用它。

if (root == NULL) 
{
    root = new Node;
    return;
}

但您必须稍后删除此节点。或者您可以使用智能指针,请参阅this

阅读thisthis了解详情。

以下代码正是您所期望的。但是它不会删除会导致内存泄漏的已创建节点,因此必须改进此代码,但这是一个单独的问题。

#include <numeric>
#include <vector>
#include <cstdio>
#include <cstdlib>
using namespace std;

struct Node {
    Node* left;
    Node* right;
    Node* parent;
    int value;
    int count_leafs;
    int height;
};

Node* root;


void insert2(int p, int value, Node* node, int left)
{
    //printf("insert %d %d - (%d, %d) %d \n", p, value, node->left, node->right, left);

    if (root == NULL) {
        //  creating a tree root

        Node* new_node = new Node;
        new_node->left = NULL;
        new_node->right = NULL;
        new_node->parent = NULL;

        root = new_node;

        root->value = value;
        root->count_leafs = 1;
        root->height = 1;
        return;
    }

    if (node->left == NULL && node->right == NULL) {
        //  joining value to the leaf

        Node* new_parent = new Node;
        new_parent->count_leafs = 2;
        new_parent->height = 2;
        new_parent->value = node->value + value;
        new_parent->parent = node->parent;
        new_parent->left = NULL;
        new_parent->right = NULL;

        Node* new_leaf = new Node;
        new_leaf->value = value;
        new_leaf->count_leafs = 1;
        new_leaf->left = NULL;
        new_leaf->right = NULL;
        new_leaf->height = 1;
        new_leaf->parent = new_parent;

        new_parent->left = new_leaf;
        new_parent->right = node;


        if (node->parent != NULL && node->parent->left != NULL && node->parent->left == node) {
            printf("a");
            node->parent->left = new_parent;
        }

        if (node->parent != NULL && node->parent->right != NULL && node->parent->right == node) {
            printf("b");
            node->parent->right = new_parent;
        }

        node->parent = new_parent;

        return;
    }

    //printf("GOTO: %d %d \n", left + node->left->count_leafs, p);

    node->value += value;
    node->count_leafs += 1;

    if (left + node->left->count_leafs + 1 >= p) {
        //printf("W left\n");
        insert2(p, value, node->left, left);
    }
    else {
        //printf("W right\n");
        insert2(p, value, node->right, left + node->left->count_leafs);
    }
}


void insert(int p, int value)
{
    insert2(p, value, root, 0);
}

int main()
{
    Node new_root;
    root = NULL;

    new_root.value = 10;
    new_root.height = 2;
    new_root.count_leafs = 2;
    new_root.parent = NULL;
    root = &new_root;

    Node left;
    left.value = 6;
    left.height = 1;
    left.count_leafs = 1;
    left.parent = root;
    left.left = NULL;
    left.right = NULL;

    Node right;
    right.value = 4;
    right.height = 1;
    right.count_leafs = 1;
    right.parent = root;
    right.left = NULL;
    right.right = NULL;

    root->left = &left;
    root->right = &right;

    // PLACE A

    insert(0, 1);

    // PLACE B

    return 0;
}