紅黑樹簡介
紅黑樹是每個節點都帶有顏色屬性的二叉查找樹,顏色或紅色或黑色。
紅黑樹的模擬過程可以看鏈接:InsertSortion
紅黑樹有五個性質:
性質1. 節點是紅色或黑色。
性質2. 根節點是黑色。
性質3. 每個葉節點(NIL節點,空節點)是黑色的。
性質4. 每個紅色節點的兩個子節點都是黑色。(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點)
性質5. 從任一節點到其每個葉子的所有路徑都包含相同數目的黑色節點。
實現過程
什麼情況下會破壞紅黑樹呢?參照鏈接:紅黑樹(一)之 原理和算法詳細介紹
除了根節點,插入的節點都是紅色的。
總結一下就是出現以下幾種情況:
對於前四種情況,我們通過左旋右旋操作去解決。(注:關於什麼是左旋和右旋可以參照鏈接C語言 AVL樹
最後一種情況,操作則不一樣:
所以對於紅黑樹的插入從操作上來看則只是比AVL樹多了最後一種情況。
代碼實現
節點
typedef struct Bi{
int val;
int pos;
int color;
struct Bi *parent;
struct Bi *left_child;
struct Bi *right_child;
} Btree, *BtreePtr;
ADT:
#define COLOR(p) ( (p==NULL) ? BLACK : (((BtreePtr)(p))->color) )
#define REB 1
#define BLACK 2
BtreePtr rightRotateRB(BtreePtr a) ;
BtreePtr leftRotateRB(BtreePtr a);
BtreePtr rightLeftRotateRB(BtreePtr a);
BtreePtr leftRightRotateRB(BtreePtr a);
BtreePtr _checkColor(BtreePtr p); //檢查節點之後兩層節點是否出現失衡,並讓樹平衡
BtreePtr _insertRBTree(BtreePtr p, const int key, const int pos);
BtreePtr insertRBTree(BtreePtr root, const int key, const int pos);
完整代碼
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#define COLOR(p) ( (p==NULL) ? BLACK : (((BtreePtr)(p))->color) )
#define REB 1
#define BLACK 2
typedef struct Bi{
int val;
int pos;
int color;
struct Bi *parent;
struct Bi *left_child;
struct Bi *right_child;
} Btree, *BtreePtr;
int midSearch(const BtreePtr a, const int key) {
if (a != NULL) {
if (key > a->val) {
return midSearch(a->right_child, key);
}
else if(key < a->val) {
return midSearch(a->left_child, key);
}
else {
return a->pos;
}
}
else {
return -1;
}
}
void freeTree(BtreePtr b) {
if (b->right_child !=NULL) {
freeTree(b->right_child);
}
if (b->left_child != NULL) {
freeTree(b->left_child);
}
}
BtreePtr leftRotateRB(BtreePtr p) {
BtreePtr b = (BtreePtr)malloc(sizeof(Btree));
b = p->right_child;
p->right_child = b->left_child;
p->color = REB;
b->color = BLACK;
b->left_child = p;
b->parent = p->parent;
b->left_child->parent = b;
return b;
}
BtreePtr rightRotateRB(BtreePtr p) {
BtreePtr b = (BtreePtr)malloc(sizeof(Btree));
b = p->left_child;
p->left_child = b->right_child;
p->color = REB;
b->color = BLACK;
b->right_child = p;
b->parent = p->parent;
b->right_child->parent = b;
return b;
}
BtreePtr rightleftRotateRB(BtreePtr p) {
p->right_child = rightRotateRB(p->right_child);
p = leftRotateRB(p);
return p;
}
BtreePtr leftrightRotateRB(BtreePtr p) {
p->right_child = leftRotateRB(p->right_child);
p = rightRotateRB(p);
return p;
}
BtreePtr _checkColor(BtreePtr p) {
int p_color = COLOR(p);
int right = COLOR(p->right_child);
int left = COLOR(p->left_child);
if (right == REB && left == BLACK) {
int right_left = COLOR(p->right_child->left_child);
int right_right = COLOR(p->right_child->right_child);
if (right_right == REB) {
p = leftRotateRB(p);
}
else if (right_left == REB) {
p = rightleftRotateRB(p);
}
}
else if (left == REB && right == BLACK) {
int left_right = COLOR(p->left_child->right_child);
int left_left = COLOR(p->left_child->left_child);
if (left_left == REB) {
p = rightRotateRB(p);
}
else if (left_right == REB) {
p = leftrightRotateRB(p);
}
}
else if (right == REB && left == REB) {
int left_right = COLOR(p->left_child->right_child);
int left_left = COLOR(p->left_child->left_child);
int right_left = COLOR(p->right_child->left_child);
int right_right = COLOR(p->right_child->right_child);
if (left_right == REB || left_left == REB || right_left == REB || right_right == REB) {
if (p->parent != NULL) {
p->color = REB;
}
p->left_child->color = BLACK;
p->right_child->color = BLACK;
}
}
return p;
}
BtreePtr _insertRBTree(BtreePtr p, const int key, const int pos) {
if (p == NULL) {
BtreePtr b = (BtreePtr)malloc(sizeof(Btree));
if (b != NULL) {
memset(b, 0, sizeof(Btree));
b->val = key;
b->pos = pos;
b->color = REB;
p = b;
}
else {
return NULL;
}
}
else
{
if (key < p->val) {
p->left_child = _insertRBTree(p->left_child, key, pos);
p->left_child->parent = p;
}
else {
p->right_child = _insertRBTree(p->right_child, key, pos);
p->right_child->parent = p;
}
}
p = _checkColor(p);
return p;
}
BtreePtr insertRBTree(BtreePtr root, const int key, const int pos) {
if (root == NULL) {
BtreePtr p = (BtreePtr)malloc(sizeof(Btree));
if (p != NULL) {
memset(p, 0, sizeof(Btree));
p->val = key;
p->pos = pos;
p->color = BLACK;
root = p;
}
else {
puts("內存不足");
}
}
else
{
root = _insertRBTree(root, key, pos);
}
return root;
}
int RBTreeSearch(const int *a, const int length, const int key) {
BtreePtr root = NULL;
for (int i = 0; i < length; i++) {
root = insertRBTree(root, a[i], i); //構建二叉樹
}
int pos = midSearch(root, key);
freeTree(root); //不能直接使用free(b)
return pos;
}
void main() {
const int length = 6;
int my_array[6] = { 5, 7, 9,11 ,8,10};
printf("%d \n", RBTreeSearch(my_array, length, 7));
}