我有一个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_child
是 NULL
并在 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 回答
看看你的代码的这一部分:
在
insert(5)
主要发生了什么?第二个if条件成功,所以你调用insert(leaf->left_child, key)
,但由于这里的叶子是根,它还没有任何子代,所以我们再次使用leaf = nullptr输入相同的方法 . 当leaf == nullptr
(第一个if条件)时,您只需创建一个节点,但不要将其附加到树的任何位置 .这就解释了为什么你有这种模式 . 现在,树木创建的整个过程需要重新思考 . 问题是几乎所有节点都有一个非零左右子节点 .