zoukankan      html  css  js  c++  java
  • 数据结构拾遗(3) --红黑树的设计与实现(下)

    完整源代码: http://download.csdn.net/detail/hanqing280441589/8450041

     

    红黑节点设计与实现

    template <typename Comparable>
    class RedBlackNode
    {
        friend class RedBlackTree<Comparable>;
    //所有的成员都是private
    private:
        RedBlackNode(const Comparable &theElement = Comparable(),
                     RedBlackNode *theLeft = NULL,
                     RedBlackNode *theRight = NULL,
                     int theColor = RedBlackTree<Comparable>::BLACK)
            : element(theElement), left(theLeft), right(theRight), color(theColor) {}
    
        //数据成员
        Comparable element;
        RedBlackNode *left;
        RedBlackNode *right;
        int color;
    };

    红黑树的设计

    template <typename Comparable>
    class RedBlackTree
    {
    //类型定义
    public:
        typedef RedBlackNode<Comparable> Node;
        enum COLOR {RED, BLACK};
    
    //开放的接口
    public:
        explicit RedBlackTree(const Comparable & negInf);
        ~RedBlackTree();
    
        void insert(const Comparable &x);
        bool isEmpty() const;
        void makeEmpty();
    
        Gref<Comparable> find(const Comparable & x) const;
        Gref<Comparable> findMin() const;
        Gref<Comparable> findMax() const;
    
    //实用的私有操作
    private:
        //自动处理: [1]重新染色; [2]:自动旋转
        void handleReorient(const Comparable &item);
        //自动旋转函数(返回旋转以后的theParent子树的根)
        Node *rotate(const Comparable & item, Node *theParent);
    
        /**单旋转**/
        //向右转(带着右孩子)
        void rotateWithLeftChild(Node *& k2);
        //向左转(带着左孩子)
        void rotateWithRightChild(Node *& k1);
    
        //递归删除所有节点
        void reclainMemory(Node *t) const;
    
    private:
        //指向红黑树的头(伪根节点)
        Node *header;
        Node *nullNode;
    
        //在insert时使用
        Node *current;  //当前节点
        Node *parent;   //父节点
        Node *grand;    //祖父节点
        Node *great;    //曾祖父节点
    };

    红黑树的实现

    //红黑树构造函数
    template <typename Comparable>
    RedBlackTree<Comparable>::RedBlackTree(const Comparable & negInf)
    {
        nullNode = new RedBlackNode<Comparable>;
        //nullNode 的左右子节点都指向自己
        nullNode->left = nullNode->right = nullNode;
    
        header = new RedBlackNode<Comparable>(negInf, nullNode, nullNode);
    }
    //红黑树析构函数: 完善版本
    template <typename Comparable>
    RedBlackTree<Comparable>::~RedBlackTree()
    {
        if (!isEmpty())
            makeEmpty();
    
        delete nullNode;
        delete header;
    }
    /**红黑树最复杂的操作 ** insert **/
    template <typename Comparable>
    void RedBlackTree<Comparable>::insert(const Comparable &x)
    {
        current = parent = grand = great = header;
        nullNode->element = x;
    
        while (current->element != x)
        {
            //让祖父成为曾祖父, 父亲成为祖父, 自己成为父亲
            //每个节点都成长一辈
            great = grand;
            grand = parent;
            parent = current;
            current = (x < current->element) ? current->left : current->right;
    
            //处理1. 如果current节点有两个红色孩子
            if ((current->left->color == RED) && (current->right->color == RED))
                handleReorient( x );
        }
    
        //如果树中包含相同的元素
        if (current != nullNode)
            throw DuplicateItemException();
    
        current = new Node(x, nullNode, nullNode);
        if (x < parent->element)
            parent->left = current;
        else
            parent->right = current;
    
        //+ 处理2. 如果新插入的节点破坏了红黑规则
        handleReorient( x );
    }
    /**自动平衡函数:
        [1]重新染色
        [2]自动旋转
    */
    template <typename Comparable>
    void RedBlackTree<Comparable>::handleReorient(const Comparable & item)
    {
        // 将current节点染成红色
        current->color = RED;
        // 将current的left和right节点染成黑色
        current->left->color = current->right->color = BLACK;
    
        // 如果current节点的父节点也是红的 -> 单旋转 or 双旋转
        if( parent->color == RED )
        {
            //则将其祖父(爷爷)的颜色染成红色
            grand->color = RED;
    
            //然后判断新插入的节点是否是内部孙子?
            //如果是, 则增加一次旋转->构成双旋转
    
            //if注释: 如果该节点小于爷爷, 小于爸爸, 这两种情况不同时满足
            //则说明其是爷爷的内孙子
            if( (item < grand->element) != (item < parent->element) )
            {
                // 则依grand(祖父)节点进行旋转
                parent = rotate( item, grand );  // Start double rotate
            }
            // 则依great(曾祖父)节点进行旋转
            current = rotate( item, great );
    
            //令当前节点为黑色
            current->color = BLACK;
        }
    
        //根节点必须是黑色的
        header->right->color = BLACK; // Make root black
    }
    // 自动判断并进行旋转函数
    template <typename Comparable>
    typename RedBlackTree<Comparable>::Node *
    RedBlackTree<Comparable>::rotate(const Comparable &item,
                                     Node *theParent )
    {
        //位于theParent的左子树
        if( item < theParent->element )
        {
            //如果为真, 则说明theParent->left有左孩子,
            //否则, 有右孩子
            item < theParent->left->element ?
            //如果theParent左边有一棵子树, 则以theParent->left
            //为轴, 向右转
            rotateWithLeftChild( theParent->left )  :  // LL
            //如果theParent右边有一棵子树, 则以theParent->left
            //为轴, 向左转
            rotateWithRightChild( theParent->left ) ;  // LR
    
            return theParent->left;     //返回左子树
        }
        else    //位于右子树
        {
            //如果为真, 则说明theParent->right有左孩子,往右转
            //否则, 有右孩子, 往左转
            item < theParent->right->element ?
            rotateWithLeftChild( theParent->right ) :  // RL
            rotateWithRightChild( theParent->right );  // RR
    
            return theParent->right;    //返回右子树
        }
    }
    /** 右(单)旋转 **/
    template <typename Comparable>
    void RedBlackTree<Comparable>::rotateWithLeftChild(Node *& k2)
    {
        Node *k1 = k2->left;
        k2->left = k1->right;
    
        k1->right = k2;
        k2 = k1;
    }
    /** 左(单)旋转 **/
    template <typename Comparable>
    void RedBlackTree<Comparable>::rotateWithRightChild(Node *& k1)
    {
        Node * k2 = k1->right;
        k1->right = k2->left;
    
        k2->left = k1;
        k1 = k2;
    }
    template <typename Comparable>
    Gref<Comparable> RedBlackTree<Comparable>::find(const Comparable &x) const
    {
        if (isEmpty())
            return Gref<Comparable>();
    
        nullNode->element = x;
        Node *iter = header->right;
    
        while (true)
        {
            if (x < iter->element)
                iter = iter->left;
            else if (x > iter->element)
                iter = iter->right;
    
            //如果 x == iter->element
            else if (iter != nullNode)
                return Gref<Comparable>(iter->element) ;
            else
                return Gref<Comparable>();
        }
    }
    template <typename Comparable>
    Gref<Comparable> RedBlackTree<Comparable>::findMax() const
    {
        if (isEmpty())
            return Gref<Comparable>();
    
        Node *iter = header->right;
        while (iter->right != nullNode)
        {
            // 一直向右走
            iter = iter->right;
        }
    
        return Gref<Comparable>(iter->element);
    }
    template <typename Comparable>
    Gref<Comparable> RedBlackTree<Comparable>::findMin() const
    {
        if (isEmpty())
            return Gref<Comparable>();
    
        Node *iter = header->right;
        while (iter->left != nullNode)
        {
            // 一直向左走
            iter = iter->left;
        }
    
        return Gref<Comparable>(iter->element);
    }
    template <typename Comparable>
    bool RedBlackTree<Comparable>::isEmpty() const
    {
        if (header->right == nullNode)
            return true;
        return false;
    }
    template <typename Comparable>
    void RedBlackTree<Comparable>::makeEmpty()
    {
        reclainMemory(header->right);
        header->right = nullNode;
    }
    template <typename Comparable>
    void RedBlackTree<Comparable>::reclainMemory(Node *t) const
    {
        //t == t->left的时候, 是当t==nullNode时
        if (t != t->left)
        {
            reclainMemory(t->left);
            reclainMemory(t->right);
            delete t;
        }
    }

    Gref包装器的设计与实现

    template <typename Object>
    class Gref
    {
    public:
        Gref(): obj(NULL) {}
        explicit Gref(const Object &x)
            : obj(& x) {}
    
        const Object &get() const
        {
            if (isNull())
                throw NullPointerException();
            else
                return * obj;
        }
    
        bool isNull() const
        {
            if (obj == NULL)
                return true;
            return false;
        }
    
    private:
        const Object * obj;
    };

    Exception的设计与实现

    class DSException
    {
    public:
        typedef std::string string;
    
    public:
        DSException(const string &_msg = string())
            :message(_msg) {}
        virtual ~DSException() {}
    
    
        virtual string what() const
        {
            return message;
        }
        virtual string toString() const
        {
            return "Exception " + message;
        }
    
    private:
        string message;
    };
    
    class DuplicateItemException : public DSException
    {
    public:
        DuplicateItemException(const string &_msg = string())
            : DSException(_msg) {}
    };
    
    class NullPointerException : public DSException
    {
    public:
        NullPointerException(const string &_msg = string())
            : DSException(_msg) {}
    };

    测试代码

    int main()
    {
        const int NEG_INF = -999999;
        RedBlackTree<int> tree(NEG_INF);
    
        tree.insert(50);
        tree.insert(40);
        tree.insert(30);
        tree.insert(10);
        tree.insert(55);
        tree.insert(88);
        tree.insert(200);
        tree.insert(100);
        tree.insert(70);
        tree.insert(80);
        tree.insert(650);
    
    
        Gref<int> g = tree.findMin();
        cout << "Min = " << g.get() << endl;
        g = tree.findMax();
        cout << "Max = " << g.get() << endl;
    
        int searchVal;
        while (cin >> searchVal)
        {
            g = tree.find(searchVal);
            if (g.isNull())
                cout << "not found" << endl;
            else
                cout << g.get() << " founded" << endl;
        }
    
        tree.makeEmpty();
        if (tree.isEmpty())
        {
            cout << "is Empty" << endl;
        }
        else
        {
            cout << "not Empty" << endl;
        }
    
        return 0;
    }

  • 相关阅读:
    ADB 操作手机的粘贴板
    JSESSIONID的简单说明
    Android无线调试出现错误的解决方法
    adb shell input text 完美支持中文输入
    SQL Server 2022来了
    新技能GET!在前端表格中花式使用异步函数的奥义
    地表最强IDE ——Visual Studio 2022正式发布
    用前端表格技术构建医疗SaaS 解决方案
    JavaScript Sanitizer API:原生WEB安全API出现啦
    突破技术限制,实现Web端静默打印
  • 原文地址:https://www.cnblogs.com/itrena/p/5926981.html
Copyright © 2011-2022 走看看