数据结构拾遗(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;
}

时间: 2024-11-04 07:59:48

数据结构拾遗(3) --红黑树的设计与实现(下)的相关文章

数据结构拾遗(1) --红黑树的设计与实现(上)

红黑树是一种自平衡的二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组(C++ STL 中的map/set).它是在1972年由Rudolf Bayer发明的,他称之为"对称二叉B树",它现代的名字是在 Leo J. Guibas 和 Robert Sedgewick 于1978年写的一篇论文中获得的.红黑树虽然很复杂,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目(来源:

数据结构拾遗(2) --红黑树的设计与实现(中)

Insert完善 根据规则4, 新增节点必须为红; 根据规则3, 新增节点之父节点必须为黑. 示例: (1)插入16(红色)/55(红色), 则既不用旋转, 也不用重新染色 (2)插入82(红色), 则违反了红黑规则, 需要进行动态的调整; 红黑树所需的处理 1.单旋转 新插入的X与其父P都是红色的, 而且X还是G的外部孙子; 2.双旋转 新插入的X与其父P都是红色的, 而且X还是G的内部孙子; 3.还需要处理有两个红色孩子的节点, 将右儿子变成黑色的, 我们只允许左儿子是红色的;方法: 旋转+

数据结构基础(18) --红黑树的设计与实现(1)

红黑树是一种自平衡的二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组(C++ STL 中的map/set).它是在1972年由Rudolf Bayer发明的,他称之为"对称二叉B树",它现代的名字是 Leo J. Guibas 和 Robert Sedgewick 于1978年写的一篇论文中获得的.红黑树虽然很复杂,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目(来源百度

数据结构基础(19) --红黑树的设计与实现(2)

双旋转 单旋转有时会出现一个问题(如下图所示): (如果内侧子孙节点[k1]过深, 则将其单向移动是不会解决问题的) 于是就有了双旋转 向右双旋转: 1.首先以k1为轴, k1与k2向左旋转; 2.然后以k3为轴, k3与旋转之后的k1向右旋转; //实现 //向右双旋转 template <typename Type> void RedBlackTree<Type>::doubleRotateWithLeftChild(Node *& k3) const { //首先将其

数据结构与算法-红黑树

前言 红黑树是工程中最常用到的一种自平衡二叉排序树,其和AVL树类似,都是在进行插入.删除时通过一定的调整操作来维持相对稳定的树高,从而获得较好的查询性能. 性质 1. 节点是红色或黑色. 2. 根节点是黑色. 3 每个叶节点(null节点)是黑色的. 4 每个红色节点的两个子节点都是黑色.(从每个叶子到根的所有路径上不能有两个连续的红色节点) 5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点. 维护红黑树形状(树高)的,主要就是4.5两条性质,性质4决定了最长的路径莫过于红黑间隔

【数据结构】平衡二叉树—红黑树

红黑树有什么特征,如何保持平衡的? 它或者是一颗空树,或者是具有一下性质的二叉查找树: 1.节点非红即黑. 2.根节点是黑色. 3.所有NULL节点称为叶子节点,且认为颜色为黑. 4.所有红节点的子节点都为黑色. 5.从任一节点到其叶子节点的所有路径上都包含相同数目的黑节点. 平衡分析: 稍微根据以上特征进一步扩展描述: 1.根据树的名称就可以知道,树的节点只有黑色和红色两种颜色,这也是为了保持平衡的一种限制方式(特征1). 2.树的头(根)跟尾(叶子节点)都是黑色的(特征2.3). 3.而红节

【数据结构05】红-黑树基础----二叉搜索树(Binary Search Tree)

目录 1.二分法引言 2.二叉搜索树定义 3.二叉搜索树的CRUD 4.二叉搜索树的两种极端情况 5.二叉搜索树总结 前言 在[算法04]树与二叉树中,已经介绍过了关于树的一些基本概念以及二叉树的前中后序遍历,而这篇文章将是在二叉树的基础上来展开讲解的二叉搜索树,也就是说二叉搜索树建立在树的基础之上.至于博主为何要花一整篇文章来讲这个二叉搜索树呢?原因很简单,红-黑树是基于二叉搜索树的,如果对二叉搜索树不了解,那还谈何红-黑树?红-黑树的重要性我想各位没吃过佩奇肉也肯定看过宜春跑....是的,j

数据结构--可迭代红黑树模板类

一.结点类与红黑树类: (一)结点类基本数据成员: 1.左右子结点指针域 2.父结点指针域,方便回访父结点 3.有序 前驱 / 后继 指针域,迭代访问元素,提供一种顺序存储的假象 4.结点颜色,利用红黑规则,保持树的平衡. (二)结点类的基本成员函数: 两个重载的构造函数,构造红色的新结点 (三)红黑树类基本数据成员: 1.头结点:保存一个据点,用来维系根节点与公用空结点 2.根结点:是红黑树的起始位置 3.空结点:作为所有空指针域的指向,一棵树只有一个 4.全局前驱.后继结点:用来使红黑树线索

15 2 用于查找的高级数据结构和算法 红黑树