首页 文章

访问冲突 . RB树没有正确创建节点

提问于
浏览
0

我有一个RB树 . 它正确地在根节点插入第一个节点,但是当在调试器上单步执行时它不会创建下一个节点,并且在尝试设置父指针时会导致访问冲突,因为它无法创建其父节点指针的节点 . 试着设定 .

源代码:

core.h

#include <iostream>
#ifndef CORE_H_
#define CORE_H_

struct node {
public:
    node(double);
    bool color; //false = red, true = black
    double key_value;
    node *left_child;
    node *right_child;
    node *parent;
};

class red_black_tree {
public:
    red_black_tree();
    ~red_black_tree();
    void print_tree();
    void insert(double key);
//  node *search(double key);
//  void delete_leaf(double key);
private:
    node *root;
    node *get_uncle(node *);
    node *get_grand(node *);
    void insert_case1(node *);
    void insert_case2(node *);
    void insert_case3(node *);
    void insert_case4(node *);
    void insert_case5(node *);
    void rotate_left(node *);
    void rotate_right(node *);
    void insert(node *leaf, double key);
    //node *search(node *leaf, double key);
//  void delete_leaf(double key);
    void print_tree(node *leaf);
    void destroy_tree(node *leaf);


};
#endif

core.cpp

#include "core.h"
#include <iostream>
node::node(double key) {
    left_child = right_child = parent = nullptr;
    color = false;
    key_value = key;
}

red_black_tree::red_black_tree() {
    root = nullptr;
}

red_black_tree::~red_black_tree() {
    if (root != nullptr) {
        destroy_tree(root);
    }

}

void red_black_tree::destroy_tree(node *leaf) {
    if (leaf->left_child!= nullptr) {
        destroy_tree(leaf->left_child);
    }
    if (leaf->left_child != nullptr) {
        destroy_tree(leaf->right_child);
    }
    delete leaf;
}

node *red_black_tree::get_grand(node *leaf) {
    if (leaf->parent != nullptr && leaf->parent->parent != nullptr)
        return leaf->parent->parent;
    else return nullptr;
}

node *red_black_tree::get_uncle(node *leaf) {
    node *g = get_grand(leaf);
    if (g == nullptr)
        return nullptr;
    if (leaf->parent == g->left_child)
        return g->right_child;
    else return g->left_child;
}

void red_black_tree::insert(double key) {
    if (root == nullptr) {
        root = new node(key);
        insert_case1(root);
    }
    else insert(root, key);
}


void red_black_tree::insert(node *leaf, double key) {
    //normal recursive binary tree insertion
    if (leaf == nullptr) {
        leaf = new node(key);
    }
    else if (key < leaf->key_value) {
        insert(leaf->left_child, key);
        leaf->left_child->parent = leaf;
        insert_case1(leaf);
    }
    else if (key >= leaf->key_value) {
        insert(leaf->right_child, key);
        leaf->right_child->parent = leaf;
        insert_case1(leaf);
    }

}

void red_black_tree::rotate_left(node *leaf) {
    node *grand = get_grand(leaf), *s_parent = grand->left_child, *left = leaf->left_child;
    grand->left_child = leaf;
    leaf->left_child = s_parent;
    s_parent->right_child = left;
    s_parent->parent = leaf;
    leaf->parent = grand;
}

void red_black_tree::rotate_right(node *leaf) {
    node *grand = get_grand(leaf), *s_parent = grand->right_child, *right = leaf->right_child;
    grand->right_child = leaf;
    leaf->right_child = s_parent;
    s_parent->left_child = right;
    s_parent->parent = leaf;
    leaf->parent = grand;
}

void red_black_tree::insert_case1(node * leaf) {
    if (leaf->parent == nullptr) {
        leaf->color = true;
    }
    else {
        insert_case2(leaf);
    }

}

void red_black_tree::insert_case2(node *leaf) {
    if (leaf->parent->color == true) {
        return;
    }
    else
        insert_case3(leaf);
}

void red_black_tree::insert_case3(node *leaf) {
    node *uncle = get_uncle(leaf), *grand;
    if ((uncle != nullptr) && (uncle->color == false)) {
        leaf->parent->color = true;
        uncle->color = true;
        grand = get_grand(leaf);
        grand->color = false;
        insert_case1(grand);
    }
    else {
        insert_case4(leaf);
    }
}

void red_black_tree::insert_case4(node *leaf) {
    node *grand = get_grand(leaf);
    if ((leaf == leaf->parent->right_child) && (leaf->parent == grand->left_child)) {
        rotate_left(leaf);
        leaf = leaf->left_child;
    }
    else if ((leaf == leaf->parent->left_child) && (leaf->parent == grand->right_child)) {
        rotate_right(leaf);
        leaf = leaf->right_child;
    }
    insert_case5(leaf);
}

void red_black_tree::insert_case5(node *leaf) {
    node *grand = get_grand(leaf);
    leaf->parent->color = true;
    grand->color = false;
    if (leaf == leaf->parent->right_child) {
        rotate_right(grand);
    }
    else
        rotate_left(grand);
}

void red_black_tree::print_tree() {
    print_tree(this->root);
}

void red_black_tree::print_tree(node *leaf) {
    if (leaf != nullptr) {
        print_tree(leaf->left_child);
        std::cout << leaf->key_value;
        print_tree(leaf->right_child);
    }
}

main.cpp中

#include "core.h"

int main() {
    red_black_tree tree;
    tree.insert(10);
    tree.insert(5);
    tree.insert(15);
    tree.print_tree();
    system("pause");
}

好吧,所以在示例 main() 中,第一个插入 tree.insert(10) 工作,它调用非递归插入,它确定根是 NULL 然后将根指针设置为一个键为10的新节点 . 第二个 tree.insert(5) ,调用非递归插入,确定根存在,然后调用递归插入 insert(root, 5) . 这确定根不是 NULL ,然后转到第一个if / else语句,并递归调用insert,如 insert(root->left_child, 5) . 这确定 root->left_childNULL 并在 root->left_child 的地址处创建新节点 . 然后该函数返回到原始插入调用并尝试设置左子项's parent to the root, causing an access violation because somehow the left child was not set. Why isn' t插入函数设置节点,我的调试器说当我单步执行时,使用 leaf = new node(5) 在最后一个递归级别创建节点,但是它退出一个级别节点仍然在那个地址 NULL

1 回答

  • 0

    看看你的代码的这一部分:

    void red_black_tree::insert(node *leaf, double key) {
        //normal recursive binary tree insertion
        if (leaf == nullptr) {
            leaf = new node(key);
        }
        else if (key < leaf->key_value) {
            insert(leaf->left_child, key);
            leaf->left_child->parent = leaf;
            insert_case1(leaf);
        } ...
    

    insert(5) 主要发生了什么?第二个if条件成功,所以你调用 insert(leaf->left_child, key) ,但由于这里的叶子是根,它还没有任何子代,所以我们再次使用leaf = nullptr输入相同的方法 . 当 leaf == nullptr (第一个if条件)时,您只需创建一个节点,但不要将其附加到树的任何位置 .

    这就解释了为什么你有这种模式 . 现在,树木创建的整个过程需要重新思考 . 问题是几乎所有节点都有一个非零左右子节点 .

相关问题