红黑树算法实现(C++版)

红黑树的概念这里介绍一篇博主觉得很好的文章:

30张图带你彻底理解红黑树

然后这里给出一个在线生成红黑树动态图的网站:
https://www.cs.usfca.edu/~galles/visualization/RedBlack.html

然后给出我的环境:
clion + cmake:
代码实现:

//
// Created by anwuq on 2020/2/2.
//
//
// Created by anwuq on 2020/2/2.
//
#include "iostream"
#include "vector"
#include 
#define red 0
#define black 1
#define BASEINDENT 30
#define max(a,b) a > b ? a : b
#define CVT(s) s ==1 ? "B" : "R"
typedef struct redblackTree {
    int color;
    int value;
    redblackTree *left;
    redblackTree *right;
    redblackTree *father;
} RBNode,*lpRBNode;

void leftRotate(lpRBNode p){
//    if(p->father!=NULL && p->right!=NULL){
      if(p->right==nullptr)return;
      if(p->father) {
          if(p->father->left==p)p->father->left = p->right;
          else if(p->father->right==p)p->father->right=p->right;
      }
      p->right->father = p->father;
      p->father = p->right;
      auto t = p->right->left;
      p->right->left = p;
      p->right = t;
      if(t!=NULL) t->father = p;
}

void rightRotate(lpRBNode p){
//    if(p->father!=NULL && p->left!=NULL){
    if(p->left==nullptr)return;
    if(p->father) {
        if(p->father->left==p)p->father->left = p->left;
        else if(p->father->right==p)p->father->right=p->left;
    }
        p->left->father = p->father;
        p->father = p->left;
        auto t =p->left->right;
        p->left->right = p;
        p->left = t;
        if(t != nullptr)t->father=p;
}
void insert_fix(lpRBNode& p){
    if(p->father == nullptr){
        p->color = black;
        return;
    }
    if(p->father->color == black){
        return;
    } else if(p->father->color== red){
        lpRBNode pp = p->father->father;

        if(pp->left && pp->left->color == red && pp->right && pp->right->color == red){
            pp->left->color = black;
            pp->right->color = black;
            pp->color = red;
            insert_fix(pp);
            // 叔叔节点不存在或黑色
        } else if (pp->left && p->father == pp->left &&
                   (pp->right == nullptr ||
                   (pp->right && pp->right->color == black))){
            if(p == p->father->left){
                p->father->color = black;
                pp->color = red;
                rightRotate(pp);
            } else if(p == p->father->right){
                leftRotate(p->father);
                insert_fix(p->left);
            }
        } else if (pp->right && p->father == pp->right &&
                   (pp->left == nullptr ||
                    (pp->left && pp->left->color == black))) {
            if(p == p->father->right) {
                p->father->color = black;
                pp->color = red;
                leftRotate(pp);
            } else if(p == p->father->left) {
                rightRotate(p->father);
                insert_fix(p->right);
            }
        }
    }
}
void insert(lpRBNode& rbt,int node){
    auto p = new RBNode;
    p->color = red;
    p->value = node;
    p->left = nullptr;
    p->right = nullptr;
    p->father = nullptr;
    // 插入情景一:树为空节点
    if(rbt == nullptr){
        rbt = p; // 指针指向同一位置
        p->color = black;
        return;
    }
    lpRBNode pp = rbt;
    //  遍历到叶子节点
    while (true){
        if(p->value<pp->value){
            if(pp->left==nullptr){
                pp->left=p;
                p->father = pp;
                break;
            }
            else pp = pp->left;
        }
        else {
            if(pp->right==nullptr){
                pp->right=p;
                p->father = pp;
                break;
            }
            else pp=pp->right;
        }
    }
    insert_fix(p);
    lpRBNode top = p;
    while (top->father!=nullptr){
        top=top->father;
    }
    rbt = top;
}
lpRBNode build_rbt(std::vector<int>& nodes){
    lpRBNode rbn;
    rbn = nullptr;
    for(auto node: nodes){
        insert(rbn,node);
    }
    return rbn;
}
lpRBNode find(lpRBNode rbn,int node){
    if(rbn == nullptr){
        return nullptr;
    }
    if(rbn->value == node){
        return rbn;
    }
    if(node < rbn->value){
        return find(rbn->left,node);
    } else {
        return find(rbn->right,node);
    }
}

lpRBNode minNode(lpRBNode node){
    while (node->left !=nullptr){
        node = node->left;
    }
    return node;
}
lpRBNode maxNode(lpRBNode node){
    while (node->right !=nullptr){
        node = node->right;
    }
    return node;
}
lpRBNode findPrecursor(lpRBNode node){
    if(node->left != nullptr){
        return maxNode(node->left);
    } else {
        lpRBNode pp;
        while (node->father != nullptr){
            pp = node->father;
            if(pp->left!=node){
                return pp;
            }
            node = pp;
        }
        return nullptr;
    }
}
lpRBNode findSuccessor(lpRBNode node){
    if(node->right != nullptr){
        return minNode(node->right);
    } else {
        lpRBNode pp;
        while (node->father != nullptr){
            pp = node->father;
            if(pp->right!=node){
                return pp;
            }
            node = pp;
        }
        return nullptr;
    }
}
void remove_fix(lpRBNode& p){
    if(p->color == 0){
        p->color = 1;
        return;
    }
    else if(p->father== nullptr)return;
    else if (p->color == 1){
        // 替换结点是其父结点的左子结点
        if(p->father->left == p){
            lpRBNode Sibl = p->father->right;
            lpRBNode SL = p->father->right->left;
            lpRBNode SR = p->father->right->right;
            if(Sibl && Sibl->color == 0){
                Sibl->color = 1;
                p->father->color = 0;
                leftRotate(p->father); // 不影响p节点
                p->father->right->color = 0;
                remove_fix(p->father);
            } else if(Sibl && Sibl->color == 1){
                if(SR && SR->color == 0){
                    Sibl->color = p->father->color;
                    p->father->color = 1;
                    SR->color = 1;
                    leftRotate(p->father);
                } else if(((SR!=nullptr && SR->color == 1) || SR==nullptr) &&
                          SL && SL->color == 0){
                    Sibl->color = p->father->color;
                    SL->color = 1;
                    rightRotate(Sibl);// 转成上个if的情况
                } else if((SR && SR->color == 1 &&
                          SL && SL->color == 1) ||
                          (SR==nullptr && SL== nullptr)) {
                    Sibl->color = 0;
                    remove_fix(p->father);
                }
            }
        } else if(p->father->right == p){
            lpRBNode Sibl = p->father->left;
            lpRBNode SL = p->father->left->left;
            lpRBNode SR = p->father->left->right;
            if(Sibl && Sibl->color == 0){
                Sibl->color = 1;
                p->father->color = 0;
                rightRotate(p->father);
                p->father->left->color = 0;
                remove_fix(p->father);
            } else if(Sibl && Sibl->color == 1){ //兄弟节点为黑色结点
                if(SL && SL->color==0){
                    Sibl->color = p->father->color;
                    p->father->color = 1;
                    SL->color = 1;
                    rightRotate(p->father);
                } else if(((SL && SL->color == 1) || SL== nullptr) &&
                          SR && SR->color == 0){
                    Sibl->color = 0;
                    SR->color = 1;
                    leftRotate(p->father->left);// 左子结点就变成红色 跟上一种情况一样
                    p->father->left->color = p->father->color;
                    p->father->color = 1;
                    p->father->left->left->color = 1;
                    rightRotate(p->father);
                } else if((SL && SL->color == 1 &&
                          SR && SR->color == 1)||
                          (SL == nullptr && SR== nullptr)){
                    Sibl->color = 0;
                    remove_fix(p->father);
                }
            }
        }
    }
}
void remove(lpRBNode& rbt,int node){
    //先找到要删节点
    lpRBNode targetNode = find(rbt,node);
    if (targetNode == nullptr) {
        std::cout<<"not found target node";
        return;
    };
    lpRBNode successor;
    // 没有子节点 直接删除
    if (targetNode->left == nullptr && targetNode->right == nullptr){
        successor = targetNode;
    }
    else if(targetNode->left == nullptr || targetNode->right == nullptr){
        if(targetNode->left != nullptr){
            successor = targetNode->left;
        } else {
            successor = targetNode->right;
        }
    }
        // 找到后继的节点 删除该替换节点
    else {
        successor = findPrecursor(targetNode);
    }
    targetNode->value = successor->value;// 先把值替换过来
    remove_fix(successor);// REW:
    if(successor->father->left == successor){
        successor->father->left = nullptr;
    } else if(successor->father->right == successor) {
        successor->father->right = nullptr;
    }
    while (rbt->father!=nullptr){
        rbt=rbt->father;
    }
}

int maxHeight(lpRBNode rbn){
    if(rbn == nullptr){
        return 0;
    }
    int lefHeight=maxHeight(rbn->left);
    int rightHeight = maxHeight(rbn->right);
    return lefHeight >= rightHeight ? lefHeight + 1 : rightHeight+1;
}
void show(lpRBNode rbn){
    if (rbn == nullptr){
        std::cout<<"red black tree is null"<<std::endl;
        return;
    }
    int i = 0;
    int height = maxHeight(rbn);
    std::vector<int> indents;
    std::vector<lpRBNode> printContainer = std::vector<lpRBNode>{rbn};
    std::vector<lpRBNode> storeContainer;
    std::cout<<"maxheight: "<<height<<std::endl;
    for(i=height;i>0;i--){
        int indent = 4*i + i;
        std::string print;
        print.assign(indent,' ');
        for(auto rbd:printContainer){
            if (rbd != nullptr) {
                print += std::to_string(rbd->value) + '(' + std::to_string(rbd->color) + ')';
                print.append(5, ' ');
                storeContainer.push_back(rbd->left);
                storeContainer.push_back(rbd->right);
            } else {
                print += "     ";
                print.append(5,' ');
                // FIXME: 这里需要修改
                storeContainer.push_back(nullptr);
                storeContainer.push_back(nullptr);
            }
        }
        printContainer.erase(printContainer.begin(),printContainer.end());
        printContainer.swap(storeContainer);

        print.erase(print.end()-5);
        print.append(indent,' ');
        std::cout<<print<<std::endl;
    }
}
int main(){
    std::vector<int> sv = std::vector<int>{16,36,19,31,20,30,10,15,25,40,22,18,29};
    lpRBNode rbtree = build_rbt(sv); // fixme: insert done!
//    std::cout<right->right->value;
    remove(rbtree,22);
    remove(rbtree,30);
    remove(rbtree,19);
    remove(rbtree,31);
    remove(rbtree,36);
    remove(rbtree,15);
    remove(rbtree,25);
    insert(rbtree,27);
    insert(rbtree,26);
    remove(rbtree,18);
    show(rbtree);

//    std::cout<
    return 0;
}

你可能感兴趣的:(算法)