关于红黑树的删除方式,网络上是众说纷纭,自己总结整理了一下,关于红黑树的性质不再重述,直接上代码,请查看删除部分的注释(delete_node_adjust函数):
#include <vector>
#include <iostream>
const int red_node = 2;
const int black_node = 1;
struct Node
{
Node(int key) : data_value(key), node_color(red_node), parent(NULL), left_child(NULL), right_child(NULL)
{
std::cout << "Node Construct" << key << std::endl;
}
~Node()
{
std::cout << "Node Destruct" << data_value << std::endl;
}
int data_value;
int node_color;
Node* parent;
Node* left_child;
Node* right_child;
};
class RedBlackTree
{
public:
RedBlackTree() : pRoot(NULL)
{
}
~RedBlackTree()
{
release();
}
public:
void insert_node(int key);
void release();
Node* search(int key);
void delete_node(int key);
void print_pre_order();
void left_rotate(int key);
void right_rotate(int key);
private:
void release(Node** pNode);
void insert_node(int key, Node** pNode, Node* pParent);
void insert_node_adjust(Node* pNode);
Node* search(int key, Node* pNode);
void delete_node(Node* pNode);
void delete_node_adjust(Node* pNode);
void print_pre_order(Node** pNode);
void left_rotate(Node* pNode);
void right_rotate(Node* pNode);
private:
Node* pRoot;
};
void RedBlackTree::delete_node(int key)
{
Node* pNode = search(key);
if (!pNode)
{
std::cout << "no node value is " << key << std::endl;
return;
}
delete_node(pNode);
return;
}
void RedBlackTree::delete_node(Node* pNode)
{
Node* pDeleteNode = pNode;
if (pNode->left_child && pNode->right_child)
{
Node* pLeftNode = pNode->right_child;
while (pLeftNode->left_child)
{
pLeftNode = pLeftNode->left_child;
}
pDeleteNode = pLeftNode;
int temp_value = pNode->data_value;
pNode->data_value = pLeftNode->data_value;
pLeftNode->data_value = temp_value;
delete_node(pLeftNode);
return;
}
else if (pNode->left_child)
{
if (pNode->parent)
{
if (pNode == pNode->parent->left_child)
{
pNode->parent->left_child = pNode->left_child;
}
else
{
pNode->parent->right_child = pNode->left_child;
}
}
else
{
pRoot = pNode->left_child;
}
}
else if (pNode->right_child)
{
if (pNode->parent)
{
if (pNode == pNode->parent->left_child)
{
pNode->parent->left_child = pNode->right_child;
}
else
{
pNode->parent->right_child = pNode->right_child;
}
}
else
{
pRoot = pNode->right_child;
}
}
else
{
if (pNode->parent)
{
if (pNode == pNode->parent->left_child)
{
pNode->parent->left_child = NULL;
}
else
{
pNode->parent->right_child = NULL;
}
}
else
{
pRoot = NULL;
}
}
delete_node_adjust(pDeleteNode);
if (pRoot)
{
pRoot->node_color = black_node;
}
delete pDeleteNode;
return;
}
void RedBlackTree::delete_node_adjust(Node* pDeleteNode)
{
if (red_node == pDeleteNode->node_color || !pDeleteNode->parent)
{
// 替换节点是红色或者黑色根节点
return;
}
// 替换节点是黑色、非根节点
Node* pParent = pDeleteNode->parent;
if (pDeleteNode == pParent->left_child)
{
Node* pBrotherNode = pParent->right_child;
if (red_node == pBrotherNode->node_color)
{
// 场景1 : 兄弟节点是红色,则父节点和其子节点均为黑色,处理方式是:
// step 1 : 将兄弟节点置黑,父节点置红
pParent->node_color = red_node;
pBrotherNode->node_color = black_node;
// step 2 : 对父节点左旋
left_rotate(pParent);
// step 3 : 重置兄弟节点,进入下一轮的判断
pBrotherNode = pParent->right_child;
}
if ((!pBrotherNode->left_child || black_node == pBrotherNode->left_child->node_color) && (!pBrotherNode->right_child || black_node == pBrotherNode->right_child->node_color))
{
// 场景 2 : 兄弟节点为黑色,并且,兄弟节点的子节点要么不存在、要么为黑,但不会为红色,该种情况下,只能向上传递、迭代处理父节点,无论通过旋转方式解决,所以:
// step 1 : 兄弟节点置红
pBrotherNode->node_color = red_node;
// step 2 : 此时替换节点和兄弟节点平衡,然后对父节点迭代处理
pDeleteNode = pParent;
delete_node_adjust(pDeleteNode);
return;
}
else
{
// 场景 3 : 兄弟节点为黑色,但是,兄弟节点的子节点存在为红色的情况,该种情况下,可通过旋转的方式解决R蛭婊唤诘闶亲蠼诘悖韵氩捎米笮姆绞嚼创恚矗? // 判断红色子节点是不是兄弟节点的右子节点,如果是则直接处理,否则,要先将其旋转到右侧,所以
// step 1 : 判断发现兄弟节点只有一个红色的子节点,并且是左节点,则着色、右旋处理
if (!pBrotherNode->right_child || black_node == pBrotherNode->right_child->node_color)
{
// 黑兄弟有红色左子节点,通过旋转,转换为红色右子节点,最后更新兄弟节点
pBrotherNode->node_color = red_node;
pBrotherNode->left_child->node_color = black_node;
right_rotate(pBrotherNode);
pBrotherNode = pParent->right_child;
}
// step 2 : 对于红色的右子节点,兄弟节点先继承父节点颜色,再置黑,旋转
pBrotherNode->node_color = pBrotherNode->parent->node_color;
pBrotherNode->parent->node_color = black_node;
pBrotherNode->right_child->node_color = black_node;
left_rotate(pBrotherNode->parent);
return;
}
}
else
{
Node* pBrotherNode = pParent->left_child;
if (red_node == pBrotherNode->node_color)
{
// parent and brother's childs must be black
pParent->node_color = red_node;
pBrotherNode->node_color = black_node;
right_rotate(pParent);
pBrotherNode = pParent->left_child;
}
if ((!pBrotherNode->left_child || black_node == pBrotherNode->left_child->node_color) && (!pBrotherNode->right_child || black_node == pBrotherNode->right_child->node_color))
{
pBrotherNode->node_color = red_node;
pDeleteNode = pParent;
delete_node_adjust(pDeleteNode);
return;
}
else
{
if (!pBrotherNode->left_child || black_node == pBrotherNode->left_child->node_color)
{
// 黑兄弟有红色右子节点
pBrotherNode->node_color = red_node;
pBrotherNode->right_child->node_color = black_node;
left_rotate(pBrotherNode);
pBrotherNode = pParent->left_child;
}
// 黑兄弟有红色左子节点
pBrotherNode->node_color = pBrotherNode->parent->node_color;
pBrotherNode->parent->node_color = black_node;
pBrotherNode->left_child->node_color = black_node;
right_rotate(pBrotherNode->parent);
return;
}
}
return;
}
void RedBlackTree::release()
{
release(&pRoot);
return;
}
void RedBlackTree::release(Node** pNode)
{
if (*pNode)
{
release(&(*pNode)->left_child);
release(&(*pNode)->right_child);
delete *pNode;
*pNode = NULL;
}
return;
}
void RedBlackTree::insert_node(int key)
{
insert_node(key, &pRoot, NULL);
return;
}
void RedBlackTree::insert_node(int key, Node** pNode, Node* pParent)
{
if (!*pNode)
{
*pNode = new Node(key);
(*pNode)->parent = pParent;
insert_node_adjust(*pNode);
}
else
{
if (key > (*pNode)->data_value)
{
// insert right node
insert_node(key, &((*pNode)->right_child), *pNode);
}
else if (key < (*pNode)->data_value)
{
// insert left node
insert_node(key, &((*pNode)->left_child), *pNode);
}
}
return;
}
void RedBlackTree::insert_node_adjust(Node* pNode)
{
// adjust inserted node's color
if (!pNode->parent)
{
// root node must be black
pNode->node_color = black_node;
}
else
{
if (black_node == pNode->parent->node_color)
{
// do nothing
}
else
{
Node* pGParent = pNode->parent->parent ? pNode->parent->parent : NULL;
if (pGParent)
{
Node* pUnic = pGParent->left_child == pNode->parent ? pGParent->right_child : pGParent->left_child;
if (pUnic && red_node == pUnic->node_color)
{
// parent and uncle to be black, gparent to be red
pGParent->node_color = red_node;
pUnic->node_color = black_node;
pNode->parent->node_color = black_node;
insert_node_adjust(pGParent);
return;
}
else if (!pUnic || black_node == pUnic->node_color)
{
if (pNode == pNode->parent->right_child && pNode->parent == pGParent->left_child)
{
// right node to left rotate
left_rotate(pNode->parent);
}
else if (pNode == pNode->parent->left_child && pNode->parent == pGParent->right_child)
{
right_rotate(pNode->parent);
}
else
{
pGParent->node_color = red_node;
pNode->parent->node_color = black_node;
if (pNode == pNode->parent->left_child && pNode->parent == pGParent->left_child)
{
right_rotate(pGParent);
}
else
{
left_rotate(pGParent);
}
}
}
}
}
}
return;
}
Node* RedBlackTree::search(int key)
{
return search(key, pRoot);
}
Node* RedBlackTree::search(int key, Node* pNode)
{
if (pNode)
{
if (pNode->data_value == key)
{
return pNode;
}
else if (pNode->data_value > key)
{
return search(key, pNode->left_child);
}
else
{
return search(key, pNode->right_child);
}
}
return NULL;
}
void RedBlackTree::print_pre_order()
{
print_pre_order(&pRoot);
std::cout << " root = " << (pRoot ? pRoot->data_value : -1) << std::endl;
return;
}
void RedBlackTree::print_pre_order(Node** pNode)
{
if (*pNode)
{
std::cout << (*pNode)->data_value << "(" << (*pNode)->node_color << ")" << " ";
print_pre_order(&(*pNode)->left_child);
print_pre_order(&(*pNode)->right_child);
}
return;
}
void RedBlackTree::left_rotate(int key)
{
Node* pNode = search(key);
if (pNode)
{
left_rotate(pNode);
}
return;
}
void RedBlackTree::left_rotate(Node* pNode)
{
Node* pRightNode = pNode->right_child;
if (!pRightNode)
{
return;
}
// left rotate has three steps, x is targeting node; y is x's right subnode; three steps's order must't be adjusted
// step 1 : y to x->parent's subnode
if (pNode->parent)
{
if (pNode == pNode->parent->left_child)
{
pNode->parent->left_child = pRightNode;
}
else if (pNode == pNode->parent->right_child)
{
pNode->parent->right_child = pRightNode;
}
}
else
{
*(&pRoot) = pRightNode;
}
pRightNode->parent = pNode->parent;
// step 2 : y's left_child to x's rightnode
pNode->right_child = pRightNode->left_child;
if (pRightNode->left_child)
{
pRightNode->left_child->parent = pNode;
}
// step 3 : y to x's parent
pNode->parent = pRightNode;
pRightNode->left_child = pNode;
return;
}
void RedBlackTree::right_rotate(int key)
{
Node* pNode = search(key);
if (pNode)
{
right_rotate(pNode);
}
return;
}
void RedBlackTree::right_rotate(Node* pNode)
{
Node* pLeftNode = pNode->left_child;
if (!pLeftNode)
{
return;
}
// right rotate has three steps, x is targeting node; y is x's left subnode; three steps's order must't be adjusted
// step 1 : y to x->parent's subnode
if (pNode->parent)
{
if (pNode == pNode->parent->left_child)
{
pNode->parent->left_child = pLeftNode;
}
else if (pNode == pNode->parent->right_child)
{
pNode->parent->right_child = pLeftNode;
}
}
else
{
*(&pRoot) = pLeftNode;
}
pLeftNode->parent = pNode->parent;
// step 2 : y's right subnode to x's left subnode
if (pLeftNode->right_child)
{
pLeftNode->right_child->parent = pNode;
}
pNode->left_child = pLeftNode->right_child;
// step 3 : y to x's parent, x to y's right subnode
pNode->parent = pLeftNode;
pLeftNode->right_child = pNode;
return;
}
int main()
{
RedBlackTree rbt;
std::vector<int> vec = {10, 6, 14, 5, 8, 11, 18, 19};
for (auto& element : vec)
{
rbt.insert_node(element);
}
rbt.print_pre_order();
rbt.delete_node(6);
rbt.print_pre_order();
return 0;
}
参考网址:
http://www.iteye.com/topic/1119331