访问冲突。 RB树未正确创建节点

时间:2015-10-09 17:59:41

标签: c++ recursion data-structures

我有一个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(root->left_child, 5)的插入。这确定root->left_childNULL并在root->left_child的地址处创建新节点。然后该函数返回到原始插入调用并尝试将左子节点的父节点设置为根,从而导致访问冲突,因为某种方式未设置左子节点。为什么insert函数没有设置节点,我的调试器说当我单步执行时,使用leaf = new node(5)在最后一级递归时创建节点,但是当它退出一个级别时节点仍然是{{ 1}}在那个地址?

0 个答案:

没有答案