C語言 紅黑樹

紅黑樹簡介

紅黑樹是每個節點都帶有顏色屬性的二叉查找樹,顏色或紅色或黑色。

紅黑樹的模擬過程可以看鏈接: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));
}
發佈了33 篇原創文章 · 獲贊 13 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章