美文网首页
Concerning Red-Black BST

Concerning Red-Black BST

作者: 刘煌旭 | 来源:发表于2021-01-03 02:15 被阅读0次

    This post presents the various Red-Black BST functions; functions that are absent can be found in
    previous posts on BST(they are the same).

    #include <stdbool.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <limits.h>
    #include <string.h>
    #include "linked_list_bag.c"
    /**
    * A implemented of red-black bst;
    * Reference: Algorithms 4ed, by R. Sedgewick & Kevin Wayne
    */
    
    #ifndef LINKED_RBBST
    #define LINKED_RBBST
    int* Int(int i) {
        int *p = (int*)malloc(sizeof(*p));
        *p = i;
        return p;
    }
    
    char* String(char *s) {
        char *p = (char*)malloc((strlen(s) + 1) * sizeof(*p));
        strcpy(p, s);
        return p;
    }
    
    int int_cmp(void *k1, void *k2) { return *(int*)k1 - *(int*)k2; }
    
    int str_cmp(void *k1, void *k2) { return strcmp((char*)k1, (char*)k2); }
    
    #define RED true
    #define BLK false
    enum RBBSTKeyType {
        RBBSTKeyTypeString = 0,
        RBBSTKeyTypeInt = 1
    };
    
    typedef struct RBBSTNodeStruct {
        void *key;
        int value;
        int count;
        bool color;
        struct RBBSTNodeStruct *left, *right;
    }*RBBSTNode;
    
    typedef struct RBBSTreeStruct {
        LinkedListBag keys;
        RBBSTNode root;
        enum RBBSTKeyType keyType;
        int (*key_cmp)(void*, void*);
    }*RBBSTree;
    
    RBBSTNode RBBSTNodeCreate(void *key, int val, bool color) {
        RBBSTNode x = (RBBSTNode)malloc(sizeof(*x));
        x->key = key;
        x->value = val;
        x->left = x->right = NULL;
        x->count = 1;
        x->color = color;
        return x;
    }
    
    void RBBSTNodeRelease(RBBSTNode node) {
        if (node == NULL) return;
        free(node->key);
        free(node);
    }
    
    RBBSTree RBBSTreeCreate(enum RBBSTKeyType keyType) {
        RBBSTree rbbst = (RBBSTree)malloc(sizeof(*rbbst));
        rbbst->keyType = keyType;
        rbbst->keys = LinkedListBagCreate();
        rbbst->root = NULL;
        if (keyType == RBBSTKeyTypeString) {
            rbbst->key_cmp = str_cmp;
        } else if (keyType == RBBSTKeyTypeInt) {
            rbbst->key_cmp = int_cmp;
        }
        return rbbst;
    }
    
    void RBBSTreeRelease_Internal(RBBSTNode root) {
        if (root == NULL) return;
        if (root->left != NULL) { RBBSTreeRelease_Internal(root->left); }
        if (root->right != NULL) { RBBSTreeRelease_Internal(root->right); }
        RBBSTNodeRelease(root);
    }
    
    void RBBSTreeRelease(RBBSTree rbbst) {
        if (rbbst == NULL) return;
        LinkedListBagRelease(rbbst->keys);
        RBBSTreeRelease_Internal(rbbst->root);
        free(rbbst);
    }
    
    int RBBSTreeCount_Internal(RBBSTNode node) { return node != NULL ? node->count : 0; }
    
    int RBBSTreeCount(RBBSTree rbbst) { return rbbst != NULL ? RBBSTreeCount_Internal(rbbst->root) : 0; }
    
    bool RBBSTNodeIsRed(RBBSTNode x) { return x!= NULL && x->color; }
    
    RBBSTNode RBBSTreeRotateLeft(RBBSTNode root) {
        RBBSTNode right = root->right;
        root->right = right->left;
        right->left = root;
        right->color = root->color;
        root->color = RED;
        right->count = root->count;
        root->count = 1 + RBBSTreeCount_Internal(root->left) + RBBSTreeCount_Internal(root->right);
        return right;
    }
    
    RBBSTNode RBBSTreeRotateRight(RBBSTNode root) {
        RBBSTNode left = root->left;
        root->left = left->right;
        left->right = root;
        left->color = root->color;
        root->color = RED;
        left->count = root->count;
        root->count = 1 + RBBSTreeCount_Internal(root->left) + RBBSTreeCount_Internal(root->right);
        return left;
    }
    
    void RBBSTreeFlipColors(RBBSTNode root) { root->left->color = root->right->color = !(root->color = !(root->color)); }
    
    RBBSTNode RBBSTreeSet_Internal(RBBSTree rbbst, RBBSTNode root, void *key, int val) {
        if (root == NULL) { return RBBSTNodeCreate(key, val, RED); }
        
        int cmp = rbbst->key_cmp(key, root->key);
        if (cmp < 0) {
            root->left = RBBSTreeSet_Internal(rbbst, root->left, key, val);
        } else if (cmp > 0) {
            root->right = RBBSTreeSet_Internal(rbbst, root->right, key, val);
        } else {
            root->value = val;
        }
        if (RBBSTNodeIsRed(root->right) && !RBBSTNodeIsRed(root->left)) root = RBBSTreeRotateLeft(root);
        if (RBBSTNodeIsRed(root->left) && RBBSTNodeIsRed(root->left->left)) root = RBBSTreeRotateRight(root);
        if (RBBSTNodeIsRed(root->left) && RBBSTNodeIsRed(root->right)) RBBSTreeFlipColors(root);
        
        root->count = RBBSTreeCount_Internal(root->left) + RBBSTreeCount_Internal(root->right) + 1;
        return root;
    }
    
    void RBBSTreeSet(RBBSTree rbbst, void *key, int val) {
        if (key == NULL || rbbst == NULL) return;
        if (rbbst->keyType == RBBSTKeyTypeString) { key = String(key); }
        rbbst->root = RBBSTreeSet_Internal(rbbst, rbbst->root, key, val);
        rbbst->root->color = BLK;
    } 
    
    int RBBSTreeGet_Internal(RBBSTree rbbst, RBBSTNode root, void *key) {
        if (root == NULL) return INT_MIN;
        int com = rbbst->key_cmp(key, root->key);
        if (com < 0) {
            return RBBSTreeGet_Internal(rbbst, root->left, key);
        } else if (com == 0) {
            return root->value;
        } else {
            return RBBSTreeGet_Internal(rbbst, root->right, key);
        }
    }
    
    int RBBSTreeGet(RBBSTree rbbst, void *key) { return key == NULL || rbbst == NULL || rbbst->root == NULL ? INT_MIN : RBBSTreeGet_Internal(rbbst, rbbst->root, key); }
    
    RBBSTNode RBBSTreeMin(RBBSTNode root) {
        if (root == NULL) return NULL;
        if (root->left != NULL) {
            return RBBSTreeMin(root->left);
        } else {
            return root;
        }
    }
    
    RBBSTNode RBBSTreeMax(RBBSTNode root) {
        if (root == NULL) return NULL;
        if (root->right != NULL) {
            return RBBSTreeMax(root->right);
        } else {
            return root;
        }
    }
    
    RBBSTNode RBBSTreeBalance(RBBSTNode root) {
        if (RBBSTNodeIsRed(root->right) && !RBBSTNodeIsRed(root->left)) root = RBBSTreeRotateLeft(root);
        if (RBBSTNodeIsRed(root->left) && RBBSTNodeIsRed(root->left->left)) root = RBBSTreeRotateRight(root);
        if (RBBSTNodeIsRed(root->left) && RBBSTNodeIsRed(root->right)) RBBSTreeFlipColors(root);
        
        root->count = RBBSTreeCount_Internal(root->left) + RBBSTreeCount_Internal(root->right) + 1;
        return root;
    }
    
    RBBSTNode RBBSTreeMoveRedLeft(RBBSTNode root) {
        RBBSTreeFlipColors(root);
        if (RBBSTNodeIsRed(root->right->left)) {
            root->right = RBBSTreeRotateRight(root->right);
            root = RBBSTreeRotateLeft(root);
        }
        return root;
    }
    
    RBBSTNode RBBSTreeDeleteMin_Internal(RBBSTNode root) {
        if (root->left == NULL) {
            RBBSTNodeRelease(root);
            return NULL;
        }
        if (!RBBSTNodeIsRed(root->left) && !RBBSTNodeIsRed(root->left->left)) { root = RBBSTreeMoveRedLeft(root); }
        root->left = RBBSTreeDeleteMin_Internal(root->left);
        return RBBSTreeBalance(root);;
    }
    
    void RBBSTreeDeleteMin(RBBSTree rbbst) {
        if (rbbst == NULL || rbbst->root == NULL) return;
        if (!RBBSTNodeIsRed(rbbst->root->left)) { rbbst->root->color = RED; }
        rbbst->root = RBBSTreeDeleteMin_Internal(rbbst->root);
        if (RBBSTreeCount_Internal(rbbst->root) != 0) rbbst->root->color = BLK;
    }
    
    RBBSTNode RBBSTreeMoveRedRight(RBBSTNode root) {
        RBBSTreeFlipColors(root);
        if (!RBBSTNodeIsRed(root->left->left)) { root = RBBSTreeRotateRight(root); }
        return root;
    }
    
    RBBSTNode RBBSTreeDeleteMax_Internal(RBBSTNode root) {
        if (RBBSTNodeIsRed(root->left)) { root = RBBSTreeRotateRight(root); }
        if (root->right == NULL) {
            RBBSTNodeRelease(root);
            return NULL;
        }
        if (!RBBSTNodeIsRed(root->right) && !RBBSTNodeIsRed(root->right->left)) { root = RBBSTreeMoveRedRight(root); }
        root->right = RBBSTreeDeleteMax_Internal(root->right);
        return RBBSTreeBalance(root);
    }
    
    void RBBSTreeDeleteMax(RBBSTree rbbst) {
        if (rbbst == NULL || rbbst->root == NULL) return;
        if (!RBBSTNodeIsRed(rbbst->root->left)) rbbst->root->color = RED;
        rbbst->root = RBBSTreeDeleteMax_Internal(rbbst->root);
        if (rbbst->root != NULL) rbbst->root->color = BLK;
    }
    
    RBBSTNode RBBSTreeDelete_Internal(RBBSTree rbbst, RBBSTNode root, void *key) {
        int com = rbbst->key_cmp(key, root->key);
        if (com < 0) {
            if (!RBBSTNodeIsRed(root->left) && !RBBSTNodeIsRed(root->left->left)) { root = RBBSTreeMoveRedLeft(root); }
            root->left = RBBSTreeDelete_Internal(rbbst, root->left, key);
        } else {
            if (RBBSTNodeIsRed(root->left)) { root = RBBSTreeRotateRight(root); }
            if (com == 0 && root->right == NULL) {//last node
                RBBSTNodeRelease(root);
                return NULL;
            }
            if (!RBBSTNodeIsRed(root->right) && !RBBSTNodeIsRed(root->right->left)) { root = RBBSTreeMoveRedRight(root); }
            com = rbbst->key_cmp(key, root->key);
            if (com == 0) {
                RBBSTNode min = RBBSTreeMin(root->right);
                root->value = min->value;
                free(root->key);
                if (rbbst->keyType == RBBSTKeyTypeString) {
                    root->key = String(min->key);
                } else if (rbbst->keyType == RBBSTKeyTypeInt) {
                    root->key = Int(*(int*)min->key);
                }
                root->right = RBBSTreeDeleteMin_Internal(root->right);
            } else {
                root->right = RBBSTreeDelete_Internal(rbbst, root->right, key);
            }
        }
        return RBBSTreeBalance(root);
    }
    
    void RBBSTreeDelete(RBBSTree rbbst, void *key) {
        if (key == NULL || rbbst == NULL || rbbst->root == NULL) return;
        if (!RBBSTNodeIsRed(rbbst->root->left)) { rbbst->root->color = RED; }
        rbbst->root = RBBSTreeDelete_Internal(rbbst, rbbst->root, key);
        if (rbbst->root != NULL) rbbst->root->color = BLK;
    }
    
    #define L -1
    #define R 1
    #define P 0
    void RBBSTreePrintLevel(RBBSTree rbbst, RBBSTNode root, int level, int k) {
        if (root == NULL) return;
        int i = level;
        while (i-- > 0) { printf("-"); }
        if (rbbst->keyType == RBBSTKeyTypeString) {
            printf("{%s %s: %i; %i %c %s}\n", k == L ? "'" : "", root->key, root->value, root->count, root->color ? 'R' : 'B', k == R ? "'" : "");
        } else if (rbbst->keyType == RBBSTKeyTypeInt) {
            printf("{%s %i: %i; %i %c %s}\n", k == L ? "'" : "", *(int*)(root->key), root->value, root->count, root->color ? 'R' : 'B', k == R ? "'" : "");
        }
        if (root->left != NULL) { RBBSTreePrintLevel(rbbst, root->left, level + 1, L); }
        if (root->right != NULL) { RBBSTreePrintLevel(rbbst, root->right, level + 1, R); }
    }
    
    void RBBSTreePrint(RBBSTree rbbst) {
        if (rbbst == NULL) return;
        RBBSTreePrintLevel(rbbst, rbbst->root, 0, P);
    }
    #endif
    

    相关文章

      网友评论

          本文标题:Concerning Red-Black BST

          本文链接:https://www.haomeiwen.com/subject/bwzyoktx.html