红黑树插入CLRS
Red-Black Tree Insertion CLRS
CLRS第3版中描述的算法看起来是错误的。我试着实现,但插入效果不好。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <algorithm>
using namespace std;
const char BLACK = 'B';
const char RED = 'R';
template <class T>
class Node{
public:
Node *left;
Node *right;
Node *parent;
char color;
T key;
Node(T x){
this->left = NULL;
this->right = NULL;
this->parent = NULL;
this->key = x;
this->color = RED;
};
virtual ~Node(){};
};
template <class T>
class RedBlackTree{
private:
int ammount;
int h;
int lastAmmount;
Node<T> *root;
Node<T> *NIL;
void destroy_node(Node<T> *&node);
Node<T> *remove_node(Node<T> *&node, T x); // not imeplemented yet
Node<T> *search_node(Node<T> *&node, T x); // not imeplemented yet
void printInfo(Node<T> *&x);
void printInOrder_node(Node<T> *&node);
void printInLevel_node(Node<T> *&node, int level);
int calculeHeight(Node<T> *&node);
void rotateLeft(Node<T> *&x);
void rotateRight(Node<T> *&y);
void insertFixUp(Node<T> *&x);
public:
RedBlackTree();
virtual ~RedBlackTree();
void destroy();
void insert(T x);
void remove(T x); // not imeplemented yet
Node<T> *search(T x); // not implemented yet
int height();
void printInOrder();
void printInLevel();
};
template <class T>
RedBlackTree<T>::RedBlackTree(){
this->ammount = 0;
this->lastAmmount = -1;
this->h = 0;
this->NIL = new Node<T>(-1);
this->NIL->color = BLACK;
this->NIL->left = this->NIL->right = this->NIL->parent = this->NIL;
this->root = this->NIL;
this->root->color = BLACK;
}
template <class T>
RedBlackTree<T>::~RedBlackTree(){
delete this->root;
}
template <class T>
void RedBlackTree<T>::destroy_node(Node<T> *&node){
if(node != NULL){
this->destroy(node->left);
this->destroy(node->right);
delete node;
}
}
template <class T>
void RedBlackTree<T>::destroy(){
this->destroy_node(this->root);
}
// RB methods
template <class T>
void RedBlackTree<T>::rotateLeft(Node<T> *&x){
Node<T> *y = x->right;
x->right = y->left;
if(y->left != this->NIL)
y->left->parent = x;
y->parent = x->parent;
if(x->parent == this->NIL)
this->root = y;
else if(x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x;
x->parent = y;
}
template <class T>
void RedBlackTree<T>::rotateRight(Node<T> *&y){
Node<T> *x = y->left;
y->left = x->right;
if(x->right != this->NIL)
x->right->parent = y;
x->parent = y->parent;
if(y->parent == this->NIL)
this->root = x;
else if(y == y->parent->left)
y->parent->left = x;
else
y->parent->right = x;
x->right = y;
y->parent = x;
}
template <class T>
void RedBlackTree<T>::insertFixUp(Node<T> *&z){
Node<T> *y;
while(z != this->root and z->parent->color == RED){
if(z->parent == z->parent->parent->left){
y = z->parent->parent->right;
if(y->color == RED){
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
}
else{
if(z == z->parent->right){
z = z->parent;
this->rotateLeft(z);
}
z->parent->color = BLACK;
z->parent->parent->color = RED;
this->rotateRight(z->parent->parent);
}
}
else{
y = z->parent->parent->left;
if(y->color == RED){
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
}
else{
if(z == z->parent->left){
z = z->parent;
this->rotateRight(z);
}
z->parent->color = BLACK;
z->parent->parent->color = RED;
this->rotateLeft(z->parent->parent);
}
}
}
this->root->color = BLACK;
}
template <class T>
void RedBlackTree<T>::insert(T val){
Node<T> *z = new Node<T>(val);
Node<T> *x = this->root;
Node<T> *y = this->NIL;
while(x != this->NIL){
y = x;
if(z->key < x->key)
x = x->left;
else
x = x->right;
}
z->parent = y;
if(y == this->NIL)
this->root = z;
else if(z->key < y->key)
y->left = z;
else
y->right = z;
z->left = this->NIL;
z->right = this->NIL;
z->color = RED;
this->insertFixUp(z);
}
template <class T>
int RedBlackTree<T>::height(){
if(this->lastAmmount == this->ammount)
return this->h;
this->h = this->calculeHeight(this->root);
this->lastAmmount = this->ammount;
return this->h;
}
template <class T>
int RedBlackTree<T>::calculeHeight(Node<T> *&node){
if(node == this->NIL)
return 0;
int l_h = this->calculeHeight(node->left);
int r_h = this->calculeHeight(node->right);
if(l_h > r_h)
return l_h+1;
return r_h+1;
}
template <class T>
void RedBlackTree<T>::printInfo(Node<T> *&x){
cout << "key=";
cout << x->key;
cout << " l->key=";
if( x->left == this->NIL)
cout << "N";
else
cout << x->left->key;
cout << " r->key=";
if( x->right == this->NIL)
cout << "N";
else
cout << x->right->key;
cout << " p->key=";
if( x->parent == this->NIL)
cout << "N";
else
cout << x->parent->key;
cout << " color=" << x->color << endl;
}
template <class T>
void RedBlackTree<T>::printInOrder_node(Node<T> *&node){
if(node != this->NIL){
this->printInOrder_node(node->left);
//cout << " " << node->key;
this->printInfo(node);
this->printInOrder_node(node->right);
}
}
template <class T>
void RedBlackTree<T>::printInOrder(){
this->printInOrder_node(this->root);
}
template <class T>
void RedBlackTree<T>::printInLevel(){
int h = this->height();
for(int i=1; i<=h; i++)
this->printInLevel_node(this->root, i);
}
template <class T>
void RedBlackTree<T>::printInLevel_node(Node<T> *&node, int level){
if(node == this->NIL)
return;
if(level == 1)
this->printInfo(node); //cout << node->key << " ";
else if(level > 1){
this->printInLevel_node(node->left, level-1);
this->printInLevel_node(node->right, level-1);
}
}
int main(){
RedBlackTree<int> *bt = new RedBlackTree<int>();
int v[9] = {11, 2, 14, 1, 7, 15, 5, 8, 4};
for(int i=0; i<9; i++){
int x = v[i];
cout << x << " ";
bt->insert(x);
}
cout << endl;
cout << "In Level:" << endl;
bt->printInLevel();
cout << endl;
delete bt;
return 0;
}
我试着在前面的主题中找到一些其他的解释,但似乎不起作用。这个代码基本上等于这本书的伪代码。主示例的预期结果是级别:
7
/
2 11
/ /
1 5 8 14
/
4 15
那么,怎么了?谢谢
考虑添加第二个节点时会发生什么。你从这个开始:
11 (black)
然后添加新节点:
11 (black)
/
2 (red)
然后尝试修复:
template <class T>
void RedBlackTree<T>::insertFixUp(Node<T> *&z){
Node<T> *y;
while(z != this->root and z->parent->color == RED){
...
}
this->root->color = BLACK;
}
注意,由于11
从一开始就是黑色的,所以控制永远不会进入循环,所以对insertFixUp
的调用什么也不做。所以你只剩下一棵红叶树,这不是一棵有效的红黑树。之后,如果您的代码希望在有效的红黑树上工作,那么它很可能会出错。
可能还有其他错误,但在尝试添加第三个节点之前,应该先让两个节点树正常工作。
相关文章:
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 预处理器:插入结构名称中的前一个行号
- 在未初始化映射的情况下,将值插入到映射的映射中
- 如何在c++中只将键插入到bimap的一侧
- 如何将结构插入到集合中并打印集合的成员
- C++json插入数组
- Visual Studio 2019:插入多个C++风格的单行注释
- nlohmann-json将一个数组插入到另一个数组中
- 有效地使用std::unordered_map来插入或增加键的值
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- 正在插入动态数组
- 插入或删除时获取usb的dos_name
- 叮叮当当在修复时插入多个"覆盖"说明符
- 链表c++插入,所有情况都已检查,但没有任何工作
- 将重物插入std::map
- C++17 - 使用自定义分配器的节点提取/重新插入 - 适用于 clang++/libc++,但不适用于 libstd
- 在数字之间插入 + 或 - 符号以使其等于整数
- 在字符串中插入空格
- 红黑树插入CLRS