数据结构 - 左倾红黑树(2-3-树推广)/ C++实现

为了保持AVL树的平衡性,插入和删除操作后,非常频繁地调整全树整体拓扑结构,代价较大。
为此在AVL树的平衡标准上进一步放宽条件,引入红黑树的结构。

一颗红黑树是满足如下红黑性质的二叉排序树:

  1. 每个结点或是红色,或是黑色的。
  2. 根结点是黑色的。
  3. 叶结点(虚构的外部节点、null节点)都是黑色的。
  4. 不存在两个相邻的红结点(即红节点的父结点和孩子结点均是黑色的)。
  5. 对每个结点,从该结点到任一叶节点的简单路径上,所含黑结点的数量相同。

红黑树的“适度平衡”,由AVL树的“高度平衡”,降低到“任意节点左右子树的高度,相差不超过2倍”,也降低了动态操作时调整的频率。对于一颗动态查找树,如果插入和删除操作比较少,查找操作比较多,采用AVL树比较合适,否则采用红黑树更合适。

常规红黑树为2-3-4-B树的推广,左倾红黑树为2-3-B树的推广,详情见《算法(第四版)》书中2-3树与红黑树一栏。

C++代码:

#include 
#include 
#include 

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

template <typename Key, typename Value>
class Node
{
public:
    Key key;
    Value val;
    Node *left, *right;
    int N; // 该棵子树中的结点占总数
    bool color;

    Node(Key key, Value val, int N, bool color) : left(0), right(0)
    {
        this->key = key;
        this->val = val;
        this->N = N;
        this->color = color;
    }
};

template <typename Key, typename Value>
class RedBlackBTS
{
    friend class Node<Key, Value>;

public:
    RedBlackBTS() : root(0) {}

    void put(Key key, Value val)
    {
        this->root = put(this->root, key, val);
        this->root->color = BLACK;
    }

    Node<Key, Value> *put(Node<Key, Value> *h, Key key, Value val)
    {
        if (h == NULL)
        {
            Node<Key, Value> *t = new Node<Key, Value>(key, val, 1, RED);
            return t;
        }

        if (key < h->key)
        {
            h->left = put(h->left, key, val);
        }
        else if (key > h->key)
        {
            h->right = put(h->right, key, val);
        }
        else
        {
            h->val = val;
        }

        // 将任意含有红色右链接的3-结点(或临时的4-结点)向左旋转。
        if (isRed(h->right) && !isRed(h->left))
            h = rotateLeft(h);
        // 将临时的4-结点中两条连续红链接中的上层链接向右旋转。
        if (isRed(h->left) && isRed(h->left->left))
            h = rotateRight(h);
        // 颜色转换并将红链接向上传递。
        if (isRed(h->left) && isRed(h->right))
            flipColors(h);

        h->N = TreeSize(h->left) + TreeSize(h->right) + 1;
        return h;
    }

    Node<Key, Value> *balance(Node<Key, Value> *h)
    {
        // 没看懂这行代码什么意思?!
        if (isRed(h->right))
            h = rotateLeft(h);
        // 经过第一步旋转,h->left必为红啊
        //  将任意含有红色右链接的3-结点(或临时的4-结点)向左旋转。
        if (isRed(h->right) && !isRed(h->left))
        {
            h = rotateLeft(h);
        }
        // 将临时的4-结点中两条连续红链接中的上层链接向右旋转。
        if (isRed(h->left) && isRed(h->left->left))
            h = rotateRight(h);
        // 颜色转换并将红链接向上传递。
        if (isRed(h->left) && isRed(h->right))
            flipColors(h);

        h->N = TreeSize(h->left) + TreeSize(h->right) + 1;
        return h;
    }
    void leval_traversal()
    {
        leval_traversal(root);
    }
    void leval_traversal(Node<Key, Value> *h)
    {
        std::cout << "leval_traversal: " << std::endl;
        std::queue<std::pair<Node<Key, Value> *, int>> q;
        q.push(std::make_pair(h, 0));
        int cnt = 0;
        while (!q.empty())
        {
            std::pair<Node<Key, Value> *, int> p = q.front();
            q.pop();
            if (p.second != cnt)
            {
                ++cnt;
                std::cout << '\n';
            }
            if ((Node<Key, Value> *)p.first == NULL)
                std::cout << "# ";
            else
            {
                std::cout << p.first->key << '/' << p.first->color << ' ';
                q.push(std::make_pair(p.first->left, cnt + 1));
                q.push(std::make_pair(p.first->right, cnt + 1));
            }
        }
        std::cout << std::endl;
    }

    Node<Key, Value> *deleteMin(Node<Key, Value> *h);
    void deleteMin();
    Node<Key, Value> *moveRedLeft(Node<Key, Value> *h);

    Node<Key, Value> *deleteMax(Node<Key, Value> *h);
    void deleteMax();
    Node<Key, Value> *moveRedRight(Node<Key, Value> *h);

    Node<Key, Value> *deleteKey(Node<Key, Value> *h, Key key);
    void deleteKey(Key key);

    Node<Key, Value> *MinNode(Node<Key, Value> *h)
    {
        return h->left == NULL ? h : MinNode(h->left);
    }

private:
    bool isRed(Node<Key, Value> *x)
    {
        if (x == NULL)
            return false; // 我们约定空连接为黑色
        return x->color == RED;
    }
    int TreeSize(Node<Key, Value> *h)
    {
        if (h == NULL)
            return 0;
        else
            return h->N;
    }
    Node<Key, Value> *root;
    Node<Key, Value> *rotateLeft(Node<Key, Value> *h);
    Node<Key, Value> *rotateRight(Node<Key, Value> *h);
    void flipColors(Node<Key, Value> *h);
    void flipColors_delete(Node<Key, Value> *h)
    {
        h->color = BLACK;
        h->left->color = RED;
        h->right->color = RED;
    }
};

template <typename Key, typename Value>
Node<Key, Value> *RedBlackBTS<Key, Value>::rotateLeft(Node<Key, Value> *h)
{
    if (h->right == NULL)
        return h;
    Node<Key, Value> *x = h->right;
    h->right = x->left;
    x->left = h;
    x->color = h->color;
    h->color = RED;
    x->N = h->N;
    h->N = TreeSize(h->left) + TreeSize(h->right) + 1;
    return x;
}

template <typename Key, typename Value>
Node<Key, Value> *RedBlackBTS<Key, Value>::rotateRight(Node<Key, Value> *h)
{
    if (h->left == NULL)
        return h;
    Node<Key, Value> *x = h->left;
    h->left = x->right;
    x->right = h;
    x->color = h->color;
    h->color = RED;
    x->N = h->N;
    h->N = TreeSize(h->left) + TreeSize(h->right) + 1;
    return x;
}

template <typename Key, typename Value>
void RedBlackBTS<Key, Value>::flipColors(Node<Key, Value> *h)
{
    h->color = RED;
    h->left->color = BLACK;
    h->right->color = BLACK;
}

template <typename Key, typename Value>
Node<Key, Value> *RedBlackBTS<Key, Value>::moveRedLeft(Node<Key, Value> *h)
{
    // 假设结点h为红结点且h->left与h->left->left均为黑色。
    // 将h->left或h->left的紫结点之一变红。
    flipColors_delete(h);
    if (isRed(h->right->left))
    {
        h->right = rotateRight(h->right);
        h = rotateLeft(h);
    }
    return h;
}

template <typename Key, typename Value>
void RedBlackBTS<Key, Value>::deleteMin()
{
    // 确保根结点为3-结点
    if (!isRed(root->left) && !isRed(root->right))
    {
        root->color = RED;
    }
    root = deleteMin(root);
    if (root != NULL)
        root->color = BLACK;
}

template <typename Key, typename Value>
Node<Key, Value> *RedBlackBTS<Key, Value>::deleteMin(Node<Key, Value> *h)
{
    // std::cout << "moveRedLeft: ";
    // leval_traversal(h);
    // 删除操作
    if (h->left == NULL)
    {
        free(h);
        return NULL;
    }
    // 将3-结点与4-结点下移
    if (!isRed(h->left) && !isRed(h->left->left))
    {
        h = moveRedLeft(h);
    }
    h->left = deleteMin(h->left);
    return balance(h);
}

template <typename Key, typename Value>
Node<Key, Value> *RedBlackBTS<Key, Value>::moveRedRight(Node<Key, Value> *h)
{
    // 假设结点h为红结点且h->left与h->right->left均为黑色。
    // 将h->left或h->left的子结点之一变红。
    flipColors_delete(h);
    if (!isRed(h->left->left))
    {
        h = rotateRight(h);
    }
    return h;
}

template <typename Key, typename Value>
void RedBlackBTS<Key, Value>::deleteMax()
{
    // 确保根结点为3-结点
    if (!isRed(root->left) && !isRed(root->right))
    {
        root->color = RED;
    }
    root = deleteMax(root);
    if (root != NULL)
        root->color = BLACK;
}

template <typename Key, typename Value>
Node<Key, Value> *RedBlackBTS<Key, Value>::deleteMax(Node<Key, Value> *h)
{
    // 将左倾红黑树在h结点规范为右倾
    if (isRed(h->left))
        h = rotateRight(h);
    if (h->right == NULL)
    {
        free(h);
        return NULL;
    }
    // 将3-结点与4-结点下移
    if (!isRed(h->right) && !isRed(h->right->left))
    {
        h = moveRedRight(h);
    }
    h->right = deleteMax(h->right);
    return balance(h);
}

template <typename Key, typename Value>
void RedBlackBTS<Key, Value>::deleteKey(Key key)
{
    if (!isRed(root->left) && !isRed(root->right))
    {
        root->color = RED;
    }
    root = deleteKey(root, key);
    if (root != NULL)
        root->color = BLACK;
}

template <typename Key, typename Value>
Node<Key, Value> *RedBlackBTS<Key, Value>::deleteKey(Node<Key, Value> *h, Key key)
{
    if (key < root->key)
    {
        if (!isRed(h->left) && !isRed(h->left->left))
        {
            h = moveRedLeft(h);
        }
        h->left = deleteKey(h->left, key);
    }
    else
    {
        if (isRed(h->left))
        {
            h = rotateRight(h);
        }
        // 在叶子结点,没有右结点,根据第一行代码可知,当前必没有左节点,因此可以直接进行删除操作。
        if(key == h->key && h->right == NULL) {
            return NULL;
        }
        if (!isRed(h->right) && !isRed(h->right->left))
        {
            h = moveRedRight(h);
        }
        if(key == h->key) {
            Node<Key, Value>* t = MinNode(h->right);
            h->val = t->val;
            h->key = t->key;
            h->right = deleteMin(h->right);
        }
        else h->right = deleteKey(h->right, key);
    }
    return balance(h);
}

int main()
{
    RedBlackBTS<int, int> rbt;
    for (int i = 7; i > 0; --i)
    {
        rbt.put(i, 1);
    }
    rbt.leval_traversal();
    rbt.deleteMin();
    rbt.leval_traversal();
    rbt.deleteMax();
    rbt.leval_traversal();
    rbt.deleteKey(4);
    rbt.leval_traversal();
}

输出结果:
数据结构 - 左倾红黑树(2-3-树推广)/ C++实现_第1张图片

你可能感兴趣的:(#,数据结构,数据结构,c++,算法)