鱼C论坛

 找回密码
 立即注册
查看: 2875|回复: 1

[技术交流] C++版本的二叉搜索树(LLRB平衡)

[复制链接]
发表于 2014-3-1 17:16:54 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 andalousie 于 2014-3-1 17:19 编辑

不久前我曾发布过一个未平衡的二叉搜索树,时至今日,我觉得是时候发布一个基本平衡的左偏红黑树(LLRB)来取代原来的二叉树了。仍将沿用原来的queue.h和main.cpp,只是基于原来的BST做了修改。不多说了,下面分享代码。
BST.h
#if !defined (BST_H)
#defind BST_H
#include "queue.h"

template<typename Index, typename Value>
class BST
{
private:
        const bool RED;
        const bool BLACK;
        struct Node
        {
                Node(Index k, Value v, int n, bool cl)
                :key(k), val(v), N(n), 
                 left(0), right(0), color(cl)
                {}
                Index key;
                Value val;
                Node *left, *right;
                bool  color; // color of parent link
                int   N;
        };
        Node *root;
        bool isRed(Node* x)
        {
                if(!x) return false;
                return x->color = RED;
        }

        Node* rotateLeft(Node* h)
        {
                assert (isRed(h->right));
                Node *x = h->right;
                h->right = x->left;
                x->left = h;
                x->color = h->color;
                h->color = RED;
                x->N = h->N;
                h->N = 1 + size(h->left)
                        + size(h->right);
                return x;
        }

        Node* rotateRight(Node* h)
        {
                assert (isRed(h->left));
                Node *x = h->left;
                h->left = x->right;
                x->right = h;
                x->color = h->color;
                h->color = RED;
                x->N = h->N;
                h->N = 1 + size(h->left)
                        + size(h->right);
                return x;
        }

        Node* moveRedLeft(Node* h)
        { // Assuming that h is red and both h->left and h->left->left
          // are black, make h->left or one of its children red.
                flipColors(h);
                if (isRed(h->right->left))
                {
                        h->right = rotateRight(h->right);
                        h = rotateLeft(h);
                }
                return h;
        }

        void flipColors(Node* h)
        {
                h->color = !h->color;
                h->left->color = !h->left->color;
                h->right->color = !h->right->color;
        }

        Node* balance(Node* h) 
        {
                assert(h);
                if (isRed(h->right) && !isRed(h->left)) h = rotateLeft(h);
                if (isRed(h->left) && isRed(h->left->left)) h = rotateRight(h);
                if (isRed(h->left) && isRed(h->right)) flipColors(h);

                h->N = size(h->left) + size(h->right) + 1;
                return h;
        }
public:
        BST(): RED(true), BLACK(false), root(0){}
        int    size() {        return size(root);        }
        bool isEmpty() { return !root; }
        Index min()        { return min(root)->key; }

        Index floor(Index key)
        {
                Node *x = floor(root, key);
                if(!x) return 0;
                return x->key;
        }

        Value get(Index key) { return get(root, key); }

        void put(Index key, Value val)
        { // Search for key. Update value if found; grow table if new.
                root = put(root, key, val);
                root->color = BLACK;
        }

        Value select(int k) { return select(root, k)->key; }

        int rank(Index key) { return rank(key, root); }

        void delMin()
        {   // if both children of root are black, set root to red
                if (!isRed(root->left) && !isRed(root->right))
                        root->color = RED;
                root = delMin(root);
                if (!isEmpty()) root->color = BLACK;
        }

        // delete the key-value pair with the given key
        void del(Index key)
        {   // if both children of root are black, set root to red
                if (!isRed(root->left) && !isRed(root->right))
                        root->color = RED;
                root = del(root, key);
                if (!isEmpty()) root->color = BLACK;
        }

        void iterate()
        {
                Queue<Index> q;
                inorder(root, q);
                while(!q.empty())
                {
                        Index key =  q.pop();
                        std::cout << get(key);
                }
        }
private:
        int   size(Node *x)
        {
                if(!x) return 0;
                else   return x->N;
        }

        Node* min(Node* x)
        {
                if(!(x->left)) return x;
                return min(x->left);
        }

        Node* floor(Node* x, Index& key)
        {
                if(!x) return 0;
                int cmp = compare(key, x->key);

                if (cmp == 0) return x;

                if (cmp < 0) return floor(x->left, key);

                Node* t = floor(x->right, key);
                if(t) return t;
                else return x;
        }
        
        Value get(Node *x, Index& key)
        { // Return value associated with key in the subtree rooted at x;
          // return null if key not present in subtree rooted at x.
                if (!x) return 0;
                int cmp = compare(key, x->key);
                if (cmp < 0) return get(x->left, key);
                else if (cmp > 0) return get(x->right, key);
                else return x->val;
        }
        
        Node* put(Node* h, Index key, Value val)
        {
                if(!h)
                {
                        h = new Node(key, val, 1, RED);
                        return h;
                }
                int cmp = compare(key, h->key);
                if(cmp < 0)
                        h->left  = put(h->left, key, val);
                else if(cmp > 0)
                        h->right = put(h->right, key, val);
                else
                        h->val = val;

                return balance(h);
        }

        Node* select(Node* x, int& k)
        {   // Return Node containing key of rank k.
                if(!x) return 0;
                int t = size(x->left);
                if (t > k) return select(x->left, k);
                else if (t < k) return select(x->right, k-t-1);
                else return x;
        }

        int   rank(Index& key, Node* x)
        {
                if(!x) return 0;
                int cmp = compare(key, x->key);
                if (cmp < 0) return rank(key, x->left);
                else if (cmp > 0) return 1 + size(x->left) + rank(key, x->right);
                else return size(x->left);
        }

        Node* delMin(Node* h)
        {
                if (!(h->left)) return 0;
                if (!isRed(h->left) && !isRed(h->left->left))
                        h = moveRedLeft(h);
                h->left = delMin(h->left);
                return balance(h);
        }

        Node* del(Node* h, Index& key)
        {
                if(!h) return 0;
                int cmp = compare(key, h->key);
                /* search for key */
                if (cmp < 0)
                {
                        if (!isRed(h->left) && !isRed(h->left->left))
                                h = moveRedLeft(h);
                        h->left = del(h->left, key);
                }
                else
                {
                        if (isRed(h->left))
                                h = rotateRight(h);
                        if (!cmp && (!h->right))
                                return 0;
                        if (!isRed(h->right) && !isRed(h->right->left))
                                h = moveRedLeft(h);
                        if (!cmp)
                        {
                                /* replace with successor */
                                Node* x = min(h->right);
                                h->key = x->key;
                                h->val = x->val;
                                h->right = delMin(h->right);
                        }
                        else h->right = del(h->right, key);
                }
                return balance(h);
        }
        
        int   compare(Index& v, Index& w) const
        {
                if(v > w)      return  1;
                else if(v < w) return -1;
                return 0;
        }

        void inorder(Node* x, Queue<Index>& q)
        {
                if(!x) return;
                inorder(x->left, q);
                q.push(x->key);
                inorder(x->right, q);
        }
};

#endif
仍然采用中序遍历。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2014-3-23 13:51:51 | 显示全部楼层
总感觉在BST的initializer_list上才声明RED和BLACK的值有点晚。而且不能体现C和C++的特点。于是试着改了改代码,应用类内的enum类型。于是去掉后面的声明,并将
        const bool RED;
        const bool BLACK;
这两行改成了简单明了的
        enum { RED = true, BLACK = false };
编译通过,大家可以试一试。注意这个枚举类型是没有枚举名称的~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-22 22:14

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表