红黑树 (C++递归)

RBtree源码实现

/*
 * BinarySearchTree.h
 *  添加元素时需自己做判断元素是否合法
 *  Created on: 2020年1月29日
 *      Author: LuYonglei
 */

#ifndef SRC_BINARYSEARCHTREE_H_
#define SRC_BINARYSEARCHTREE_H_
#include <queue>

const bool RED = false;
const bool BLACK = true;

template<typename Element>
class BinarySearchTree {
public:

    BinarySearchTree(int (*cmp)(Element e1, Element e2)); //比较函数指针

    virtual ~BinarySearchTree();

    int size(); //元素的数量

    bool isEmpty(); //是否为空

    void clear() {
        //清空所有元素
        NODE *node = root_;
        root_ = nullptr;
        using namespace std;
        queue<NODE*> q;
        q.push(node);
        while (!q.empty()) {
            NODE *tmp = q.front();
            if (tmp->left != nullptr)
                q.push(tmp->left);
            if (tmp->right != nullptr)
                q.push(tmp->right);
            delete tmp;
            q.pop();
        }
    }

    void add(Element e) {
        //添加元素
        add(e, cmp_);
    }

    void remove(Element e) {
        //删除元素
        remove(Node(e, cmp_));
    }

    bool contains(Element e) {
        //是否包含某元素
        return Node(e, cmp_) != nullptr;
    }

    void preorderTraversal(bool (*visitor)(Element e)) {
        //前序遍历
        if (visitor == nullptr)
            return;
        bool stop = false; //停止标志,若stop为true,则停止遍历
        preorderTraversal(root_, stop, visitor);
    }

    void inorderTraversal(bool (*visitor)(Element e)) {
        //中序遍历
        if (visitor == nullptr)
            return;
        bool stop = false; //停止标志,若stop为true,则停止遍历
        inorderTraversal(root_, stop, visitor);
    }

    void postorderTraversal(bool (*visitor)(Element e)) {
        //后序遍历
        if (visitor == nullptr)
            return;
        bool stop = false; //停止标志,若stop为true,则停止遍历
        postorderTraversal(root_, stop, visitor);
    }

    void levelOrderTraversal(bool (*visitor)(Element e)) {
        //层序遍历,迭代实现
        if (visitor == nullptr)
            return;
        levelOrderTraversal(root_, visitor);
    }

    int height() {
        //树的高度
        return height(root_);
    }

    bool isComplete() {
        //判断是否是完全二叉树
        return isComplete(root_);
    }

private:

    int size_;

    typedef struct _Node {
        Element e;
        _Node *parent;
        _Node *left;
        _Node *right;
        bool color_;
        _Node(Element e_, _Node *parent_) :
                e(e_), parent(parent_), left(nullptr), right(nullptr), color_(
                        RED) {
            //节点构造函数
        }

        inline bool isLeaf() {
            return (left == nullptr && right == nullptr);
        }

        inline bool hasTwoChildren() {
            return (left != nullptr && right != nullptr);
        }

        inline bool isLeftChild() {
            //判断节点是否是父亲节点的左子结点
            return parent != nullptr && parent->left == this;
        }

        inline bool isRightChild() {
            //判断节点是否是父亲节点的右子结点
            return parent != nullptr && parent->right == this;
        }

        inline _Node* sibling() {
            //返回兄弟节点
            if (this->parent != nullptr) {
                if (this->isLeftChild())
                    return this->parent->right;
                else
                    return this->parent->left;
            }
            return nullptr;
        }

    } NODE;

    NODE *root_;

    int (*cmp_)(Element e1, Element e2); //为实现树的排序的个性化配置,私有成员保存一个比较函数指针

    NODE* Node(Element e, int (*cmp_)(Element e1, Element e2)) {
        //返回e元素所在的节点
        NODE *node = root_;
        while (node != nullptr) {
            int cmp = cmp_(e, node->e);
            if (cmp == 0) //找到了元素
                return node;
            if (cmp > 0) { //待寻找元素大于节点存储的元素
                node = node->right;
            } else { //待寻找元素小于节点存储的元素
                node = node->left;
            }
        }
        return nullptr;
    }

    NODE* predecessor(NODE *node) {
        //返回node的前驱节点
        if (node == nullptr)
            return nullptr;
        //前驱节点在左子树
        NODE *tmp = node->left;
        if (tmp != nullptr) {
            while (tmp->right != nullptr)
                tmp = tmp->right;
            return tmp;
        }
        //从父节点,祖父节点中寻找前驱节点
        while (node->parent != nullptr && node == node->parent->left) {
            node = node->parent;
        }
        return node->parent;
    }

    NODE* successor(NODE *node) {
        //返回node的后继节点
        if (node == nullptr)
            return nullptr;
        //后继节点在右子树
        NODE *tmp = node->right;
        if (tmp != nullptr) {
            while (tmp->left != nullptr)
                tmp = tmp->left;
            return tmp;
        }
        //从父节点,祖父节点中寻找后继节点
        while (node->parent != nullptr && node == node->parent->right) {
            node = node->parent;
        }
        return node->parent;
    }

    bool colorOf(NODE *node) {
        //返回节点的颜色
        return node == nullptr ? BLACK : node->color_;
    }

    bool isBlack(NODE *node) {
        //node是否为黑色
        return node == nullptr ? true : node->color_ == BLACK;
    }

    bool isRed(NODE *node) {
        //node是否为红色
        return node == nullptr ? false : node->color_ == RED;
    }

    NODE* color(NODE *node, bool color) {
        //对节点染色
        if (node == nullptr)
            return node;
        node->color_ = color;
        return node;
    }

    NODE* red(NODE *node) {
        //把节点染成红色
        return color(node, RED);
    }

    NODE* black(NODE *node) {
        //把节点染成黑色
        return color(node, BLACK);
    }

    void afterRotate(NODE *gNode, NODE *pNode, NODE *child) {
        //在左旋转与右旋转中统一调用
        pNode->parent = gNode->parent;
        if (gNode->isLeftChild())
            gNode->parent->left = pNode;
        else if (gNode->isRightChild())
            gNode->parent->right = pNode;
        else
            //此时gNode->parent 为nullptr,gNode为root节点
            root_ = pNode;
        if (child != nullptr)
            child->parent = gNode;
        gNode->parent = pNode;

    }

    void rotateLeft(NODE *gNode) {
        //对gNode进行左旋转
        NODE *pNode = gNode->right;
        NODE *child = pNode->left;
        gNode->right = child;
        pNode->left = gNode;
        afterRotate(gNode, pNode, child);

    }

    void rotateRight(NODE *gNode) {
        //对gNode进行右旋转
        NODE *pNode = gNode->left;
        NODE *child = pNode->right;
        gNode->left = child;
        pNode->right = gNode;
        afterRotate(gNode, pNode, child);

    }

    void afterAdd(NODE *node) {
        //添加node之后的操作
        NODE *parentNode = node->parent;
        //没有父节点时,新添加的节点是root_或者上溢到root_
        if (parentNode == nullptr) {
            black(node);
            return;
        }
        //1.当父亲节点为黑色节点时,不做任何处理,直接返回
        if (isBlack(parentNode))
            return;
        NODE *uncleNode = parentNode->sibling();
        NODE *grandNode = red(parentNode->parent);
        if (isRed(uncleNode)) {
            //2.uncle节点是红色,(上溢,只需要染色)
            black(parentNode);
            black(uncleNode);
            //祖父节点当作是新添加的节点
            afterAdd(grandNode);
            return;
        }
        //3.uncle节点是黑色或者uncle节点为null
        if (parentNode->isLeftChild()) {
            if (node->isLeftChild()) {
                //LL
                black(parentNode);
            } else {
                //LR
                black(node);
                rotateLeft(parentNode);
            }
            rotateRight(grandNode);
        } else {
            if (node->isLeftChild()) {
                //RL
                black(node);
                rotateRight(parentNode);
            } else {
                //RR
                black(parentNode);
            }
            rotateLeft(grandNode);
        }
    }

    void add(Element e, int (*cmp_)(Element e1, Element e2)) {
        //当树为空时,添加的节点作为树的根节点
        if (root_ == nullptr) {
            root_ = new NODE(e, nullptr);
            size_++;
            afterAdd(root_);
            return;
        }
        //当添加的节点不是第一个节点
        NODE *parent = root_;
        NODE *node = root_;
        int cmp = 0; //比较结果
        while (node != nullptr) {
            parent = node; //保存父节点
            cmp = cmp_(e, node->e); //由函数指针来比较
            if (cmp > 0) {
                node = node->right; //添加的元素大于节点中的元素
            } else if (cmp < 0) {
                node = node->left; //添加的元素小于节点中的元素
            } else {
                node->e = e; //相等时就覆盖
                return; //添加的元素等于节点中的元素,直接返回
            }
        }
        //判断要插入父节点的哪个位置
        NODE *newNode = new NODE(e, parent); //为新元素创建节点
        if (cmp > 0) {
            parent->right = newNode; //添加的元素大于节点中的元素
        } else {
            parent->left = newNode; //添加的元素小于节点中的元素
        }
        size_++;
        afterAdd(newNode);
    }

    void afterRemove(NODE *node) {
        //删除节点之后的操作
        //node是要被释放内存的节点或是是替代的节点
        //1.如果删除的是红色节点,直接删掉即可
        //此处代表删除的节点为红色叶子节点
        if (isRed(node)) {
            //2.如果删除的节点是黑色节点,且替代的节点为红色节点
            //此处代表删除的节点的度为1,且要删除的节点含有一个红色子节点
            black(node);
            return;
        }
        //3.如果删除的节点是黑色节点,且替代的节点为黑色节点(nullptr)
        //此处代表要删除的是黑色叶子节点或根节点
        NODE *parentNode = node->parent;
        //如果删除的是根节点
        if (parentNode == nullptr)
            return;

        //此时node为叶子节点
        //但想获得他的兄弟节点不能调用sibling(),因为在调用afterRemove()之前,若node为parent的left就已经将parent的left置为nullptr
        //若node为parent的right就已经将parent的right置为nullptr,此时再调用sibling()就会得不到准确的信息
        bool left = parentNode->left == nullptr || node->isLeftChild();
        NODE *siblingNode = left ? parentNode->right : parentNode->left;
        if (left) {
            //被删除的节点在左边,兄弟节点在右边
            if (isRed(siblingNode)) {
                //兄弟节点是红色,要转化成兄弟节点是黑色
                black(siblingNode);
                red(parentNode);
                rotateLeft(parentNode);
                //更换兄弟
                siblingNode = parentNode->right;
            }
            //以下代码处理兄弟节点是黑色(兄弟节点必然为黑色)
            if (isBlack(siblingNode->left) && isBlack(siblingNode->right)) {
                //兄弟节点没有红色子节点,父节点要向下和兄弟节点合并
                bool parentIsBlack = isBlack(parentNode);
                black(parentNode);
                red(siblingNode);
                if (parentIsBlack) {
                    //如果父亲节点是黑色,会产生下溢
                    afterRemove(parentNode);
                }
            } else {
                //兄弟节点至少有一个红色子节点,向兄弟节点借元素
                //兄弟节点的右边是黑色的,兄弟要先旋转
                if (isBlack(siblingNode->right)) {
                    rotateRight(siblingNode);
                    siblingNode = parentNode->right;
                }
                color(siblingNode, colorOf(parentNode));
                black(parentNode);
                black(siblingNode->right);
                rotateLeft(parentNode);
            }
        } else {
            //被删除的节点在右边,兄弟节点在左边
            if (isRed(siblingNode)) {
                //兄弟节点是红色,要转化成兄弟节点是黑色
                black(siblingNode);
                red(parentNode);
                rotateRight(parentNode);
                //更换兄弟
                siblingNode = parentNode->left;
            }
            //以下代码处理兄弟节点是黑色(兄弟节点必然为黑色)
            if (isBlack(siblingNode->left) && isBlack(siblingNode->right)) {
                //兄弟节点没有红色子节点,父节点要向下和兄弟节点合并
                bool parentIsBlack = isBlack(parentNode);
                black(parentNode);
                red(siblingNode);
                if (parentIsBlack) {
                    //如果父亲节点是黑色,会产生下溢
                    afterRemove(parentNode);
                }
            } else {
                //兄弟节点至少有一个红色子节点,向兄弟节点借元素
                //兄弟节点的左边是黑色的,兄弟要先旋转
                if (isBlack(siblingNode->left)) {
                    rotateLeft(siblingNode);
                    siblingNode = parentNode->left;
                }
                color(siblingNode, colorOf(parentNode));
                black(parentNode);
                black(siblingNode->left);
                rotateRight(parentNode);
            }
        }

    }

    void remove(NODE *node_) {
        //删除某一节点
        if (node_ == nullptr)
            return;
        size_--;
        //优先删除度为2的节点
        if (node_->hasTwoChildren()) {
            NODE *pre = successor(node_); //找到node_的后继节点
            node_->e = pre->e; //用后继节点的值覆盖度为2的节点的值
            //删除后继节点(后继节点的度只能为1或0)
            node_ = pre;
        }
        //此时node_的度必然为0或1
        NODE *replacement = node_->left != nullptr ? node_->left : node_->right;
        if (replacement != nullptr) {            //node_的度为1
            replacement->parent = node_->parent;
            if (node_->parent == nullptr)            //度为1的根节点
                root_ = replacement;
            else if (node_->parent->left == node_)
                node_->parent->left = replacement;
            else
                node_->parent->right = replacement;
            afterRemove(replacement);
            delete node_;
        } else if (node_->parent == nullptr) {            //node_是叶子节点,也是根节点
            root_ = nullptr;
            delete node_;
        } else {            //node_是叶子节点,但不是根节点
            if (node_->parent->left == node_)
                node_->parent->left = nullptr;
            else
                node_->parent->right = nullptr;
            afterRemove(node_);
            delete node_;
        }
    }

    void preorderTraversal(NODE *node, bool &stop, bool (*visitor)(Element e)) {
        //递归实现前序遍历
        if (node == nullptr || stop == true)
            return;
        stop = visitor(node->e);
        preorderTraversal(node->left, stop, visitor);
        preorderTraversal(node->right, stop, visitor);
    }

    void inorderTraversal(NODE *node, bool &stop, bool (*visitor)(Element e)) {
        //递归实现中序遍历
        if (node == nullptr || stop == true)
            return;
        inorderTraversal(node->left, stop, visitor);
        if (stop == true)
            return;
        stop = visitor(node->e);
        inorderTraversal(node->right, stop, visitor);
    }

    void postorderTraversal(NODE *node, bool &stop,
            bool (*visitor)(Element e)) {
        //递归实现后序遍历
        if (node == nullptr || stop == true)
            return;
        postorderTraversal(node->left, stop, visitor);
        postorderTraversal(node->right, stop, visitor);
        if (stop == true)
            return;
        stop = visitor(node->e);
    }

    void levelOrderTraversal(NODE *node, bool (*visitor)(Element e)) {
        if (node == nullptr)
            return;
        using namespace std;
        queue<NODE*> q;
        q.push(node);
        while (!q.empty()) {
            NODE *node = q.front();
            if (visitor(node->e) == true)
                return;
            if (node->left != nullptr)
                q.push(node->left);
            if (node->right != nullptr)
                q.push(node->right);
            q.pop();
        }
    }

    int height(NODE *node) {
        //某一节点的高度
        if (node == nullptr)
            return 0;
        using namespace std;
        queue<NODE*> q;
        q.push(node);
        int height = 0;
        int levelSize = 1; //每一层起始的节点个数
        while (!q.empty()) {
            NODE *node = q.front();
            levelSize--;
            if (node->left != nullptr)
                q.push(node->left);
            if (node->right != nullptr)
                q.push(node->right);
            q.pop();
            if (levelSize == 0) {
                height++;
                levelSize = q.size();
            }
        }
        return height;
    }

    bool isComplete(NODE *node) {
        if (node == nullptr)
            return false;
        using namespace std;
        queue<NODE*> q;
        q.push(node);
        bool leaf = false; //判断接下来的节点是否为叶子节点
        while (!q.empty()) {
            NODE *node = q.front();
            if (leaf && !node->isLeaf()) //判断叶子节点
                return false;
            if (node->left != nullptr) {
                q.push(node->left);
            } else if (node->right != nullptr) { //node->left == nullptr && node->right != nullptr
                return false;
            }
            if (node->right != nullptr) {
                q.push(node->right);
            } else { //node->right==nullptr
                leaf = true;
            }
            q.pop();
        }
        return true;
    }

};

template<typename Element>
BinarySearchTree<Element>::BinarySearchTree(int (*cmp)(Element e1, Element e2)) :
        size_(0), root_(nullptr), cmp_(cmp) {
    //树的构造函数
}

template<typename Element>
BinarySearchTree<Element>::~BinarySearchTree() {
    // 析构函数
    clear();
}

template<typename Element>
inline int BinarySearchTree<Element>::size() {
    //返回元素个数
    return size_;
}

template<typename Element>
inline bool BinarySearchTree<Element>::isEmpty() {
    //判断是否为空树
    return size_ == 0;
}

#endif /* SRC_BINARYSEARCHTREE_H_ */

 

main测试例程

/*
 * main.cpp
 *
 *  Created on: 2020年1月29日
 *      Author: LuYonglei
 */

#include "BinarySearchTree.h"
#include <iostream>

using namespace std;

template<typename Element>
int compare(Element e1, Element e2) {
    //比较函数,相同返回0,e1<e2返回-1,e1>e2返回1
    return e1 == e2 ? 0 : (e1 < e2 ? -1 : 1);
}

template<typename Elemnet>
bool visitor(Elemnet e) {
    cout << e << " ";
    return false; //若返回true,则在遍历时会退出
}

int main(int argc, char **argv) {
    BinarySearchTree<double> a(compare);
    a.add(55);
    a.add(87);
    a.add(56);
    a.add(74);
    a.add(96);
    a.add(22);
    a.add(62);
    a.add(20);
    a.add(70);
    a.add(68);
    a.add(90);
    a.add(50);
    a.remove(55);
    a.remove(87);
    a.remove(56);
//    a.inorderTraversal(visitor);
//    cout << endl;
//    cout << a.isComplete() << endl;
//    a.remove(55);
//    a.clear();
    a.levelOrderTraversal(visitor);
    cout << endl;
//    cout<<a.contains(0)<<endl;
}

 

原文链接: https://www.cnblogs.com/luyl/p/12256344.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    红黑树 (C++递归)

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/326794

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月1日 下午3:58
下一篇 2023年3月1日 下午3:59

相关推荐