红黑树是近似平衡的二叉搜索树。
红黑树的性质:
1,每个节点不是红色就是黑色
2,根节点必须是黑色
3,没有连续的红节点
4,每条路径上黑色节点数目相等

红黑树保证最长路径不超过最短路径的两倍。那么,为什么满足以上这些条件就能保证呢?
最短路径一定是节点全黑,要保证每条路径的黑节点数量相等,只能在两个黑节点之间添加红节点,所以最长路径不会超过最短路径的两倍。
红黑树保证效率为log2^N

如上图所示是一棵简单的红黑树,红黑树的插入要通过旋转和变色来调节平衡。

当parent是grandfather的左孩子,uncle是grandfather的右孩子时,插入可分为以下情况:

1,叔叔节点存在且为红色

Node* grandfther = parent->_parent;
            if (parent == grandfther->_left)
            {
                Node* uncle = grandfther->_right;
                if (uncle && uncle->_col == RED)
                {
                    parent->_col = BLACK;
                    uncle->_col = BLACK;
                    grandfther->_col = RED;

                    cur = grandfther;
                    parent = cur->_parent;
                }

2,叔叔节点不存在或存在且为黑

将parent变黑,grandfather变红,进行右单旋

else // u 不存在 u黑
                {
                    if(cur == parent->_right) // 双旋
                    {
                        RotateL(parent);
                        swap(cur,parent);
                    }

                    RotateR(grandfther);
                    parent->_col = BLACK;
                    grandfther->_col = RED;
                    break;
                }

3,cur是parent的右孩子,需要双旋

当parent是grandfather的右时,需要分析的情况还是以上三种,只是方向相反而已。

完整代码:

#pragma once
#include<iostream>
using namespace std;

enum Colour
{
    RED,BLACK,};

template<class K,class V>
struct RBTreeNode
{
    K _key;
    K _value;

    RBTreeNode<K,V>* _left;
    RBTreeNode<K,V>* _right;
    RBTreeNode<K,V>* _parent;

    Colour _col;

    RBTreeNode(const K& key,const V& value)
        :_key(key),_value(value),_left(NULL),_right(NULL),_parent(NULL),_col(RED)
    {}
};


template<class K,class V>
class RBTree
{
    typedef RBTreeNode<K,V> Node;
public:
    RBTree()
        :_root(NULL)
    {}

    RBTree(const RBTree<K,V>& tree)
    {
        _copy(tree._root);
    }


    ~RBTree()
    {
        _Destroy(_root);
    }

    RBTree<K,V>& operator = (const RBTree<K,V>& tree)
    {
        RBTree<K,V> tmp(tree);
        swap(_root,tree._root);
        return *this;
    }


    bool Insert(const K& key,const V& value)
    {
        if (_root == NULL)
        {
            _root = new Node(key,value);
            _root->_col = BLACK;
            return true;
        }

        Node* parent = NULL;
        Node* cur = _root;
        while (cur)
        {
            if (cur->_key < key)
            {
                parent = cur;
                cur = cur->_right;
            }
            else if (cur->_key > key)
            {
                parent = cur;
                cur = cur->_left;
            }
            else
            {
                return false;
            }
        }

        cur = new Node(key,value);
        if (parent->_key < key)
        {
            parent->_right = cur;
            cur->_parent = parent;
        }
        else
        {
            parent->_left = cur;
            cur->_parent = parent;
        }

        while (parent && parent->_col == RED)
        {
            Node* grandfather = parent->_parent;
            if (parent == grandfather->_left)
            {
                Node* uncle = grandfather->_right;
                if (uncle && uncle->_col == RED)
                {
                    parent->_col = BLACK;
                    uncle->_col = BLACK;
                    grandfather->_col = RED;

                    cur = grandfather;
                    parent = cur->_parent;
                }
                else // u 不存在 u黑
                {
                    if (cur == parent->_right) // 双旋
                    {
                        RotateL(parent);
                        swap(cur,parent);
                    }

                    RotateR(grandfather);
                    parent->_col = BLACK;
                    grandfather->_col = RED;
                    break;
                }
            }
            //parent = grandfather->right
            else if (parent == grandfather->_right)
            {
                Node* uncle = grandfather->_left;
                if (uncle && uncle->_col == RED)
                {
                    parent->_col = BLACK;
                    uncle->_col = BLACK;
                    grandfather->_col = RED;

                    cur = grandfather;
                    parent = cur->_parent;
                }
                else
                {
                    if (cur == parent->_right)
                    {
                        RotateR(parent);
                        swap(parent,cur);
                    }
                    RotateL(grandfather);
                    parent->_col = BLACK;
                    grandfather->_col = RED;
                    break;
                }
            }
        }
        _root->_col = BLACK;
        return true;
    }

    void Inorder()
    {
        _Inorder(_root);
    }

    bool IsBalance()
    {
        Node* cur = _root;
        if (_root == NULL)
        {
            return true;
        }
        //根节点是黑色
        if (_root->_col == RED)
        {
            return false;
        }
        int BlackNode = 0;
        //统计最左路径上黑色节点的数量
        while (cur)
        {
            if (cur->_col == BLACK)
            {
                ++BlackNode;
            }
            cur = cur->_left;
        }
        //一条路径上黑色节点的数量
        int num = 0;
        return _IsBlance(_root,BlackNode,num);
    }
protected:
    void _copy(Node* root)
    {
        Node* newNode = NULL;
        Node* cur = root;
        while (cur)
        {
            newNode = new Node(cur->_key,cur->_value);
            newNode->_left = _copy(cur->_left);
            newNode->_right = _copy(cur->_right);
        }
    }

    void _Destroy(Node* root)
    {
        Node* cur = root;
        if (root == NULL)
            return;
        _Destroy(cur->_left);
        _Destroy(cur->_right);
        delete cur;
        cur = NULL;
    }


    bool _IsBlance(Node* root,const int BlackNode,int num)
    {
        //一条路径已经走完
        if (root == NULL)
        {
            if (num != BlackNode)
            {
                cout << "黑色节点数量不相等" << endl;
                return false;
            }
            else
            {
                return true;
            }
        }
        if (root->_col == BLACK)
        {
            ++num;
        }
        if((root->_col == RED) && (root->_parent) && (root->_parent->_col == RED))
        {
            cout << "有连续的红节点" << root->_key << endl;
            return false;
        }
        return _IsBlance(root->_left,num)
            && _IsBlance(root->_right,num);
    }

    //右旋
    void RotateR(Node* parent)
    {
        Node* subL = parent->_left;
        Node* subLR = subL->_right;
        parent->_left = subLR;
        if (subLR)
            subLR->_parent = parent;

        subL->_right = parent;
        Node* ppNode = parent->_parent;
        parent->_parent = subL;

        if (ppNode == NULL)
        {
            _root = subL;
            subL->_parent = NULL;
        }
        else
        {
            if (ppNode->_left == parent)
            {
                ppNode->_left = subL;
            }
            else
            {
                ppNode->_right = subL;
            }
            subL->_parent = ppNode;
        }
    }

    //左旋
    void RotateL(Node* parent)
    {
        Node* subR = parent->_right;
        Node* subRL = subR->_left;

        parent->_right = subRL;
        if (subRL)
            subRL->_parent = parent;

        subR->_left = parent;
        Node* ppNode = parent->_parent;
        parent->_parent = subR;

        if (ppNode == NULL)
        {
            _root = subR;
            subR->_parent = NULL;
        }
        else
        {
            if (ppNode->_left == parent)
            {
                ppNode->_left = subR;
            }
            else
            {
                ppNode->_right = subR;
            }
            subR->_parent = ppNode;
        }
    }

    void _Inorder(Node* root)
    {
        Node* cur = root;
        if (cur == NULL)
            return;
        _Inorder(cur->_left);
        cout << cur->_key << " ";
        _Inorder(cur->_right);
    }
private:
    Node* _root;
};

void TestRBTree()
{
    RBTree<int,int> t;
    int a[] = { 16,3,7,11,9,26,18,14,15 }; for (int i = 0; i < sizeof(a) / sizeof(a[0]); ++i) { t.Insert(a[i],i); } t.Inorder(); cout << endl; cout << "IsBalance?" << t.IsBalance() << endl; } 

我们知道,红黑树是近似平衡的二叉树,那么为什么不直接使用平衡二叉树呢?
原因是红黑树最坏的情况也是log2^N,但它不像平衡二叉树需要严格控制平衡因子,红黑树只需控制节点的颜色,因此它的旋转次数相对于平衡二叉树能少一些,因此,实际中,红黑树的应用更为广泛。

红黑树的应用: 1. C++ STL库 – map 2. Java 库 3. linux内核 4. 其他一些库

【数据结构】:红黑树RB Tree的更多相关文章

  1. macos – 运行brew命令充满了’同意Xcode / iOS许可证需要管理员权限,请通过sudo以root身份重新运行.’

    所以我跑了:如果滚动到底部,可以输入“同意”,然后就可以了.

  2. ios – 仅适用于iPad的Settings.bundle?

    我有一种情况需要通过设置应用程序为我的应用程序提供一个设置.我的应用程序是通用的,但这个特殊的设置只在iPad上有意义,所以我只希望我的应用程序显示在iPad上的设置中.这可能吗?

  3. ios – Swift 4设置捆绑,获取默认值

    我创建了一个包含大约8个切换开关的设置包.我想要做的是从设置包中获取默认值.目前我现在有这两种方法:我在viewDidLoad中调用这些方法然而,这并没有得到我的默认值.如果我关闭应用程序,打开设置,调整设置并重新打开应用程序,这会产生正确的值.有没有获得默认设置?

  4. swift篇第一期:简单的数据结构

    首先我们可以去使用Playground来编码,并且会实时的显示对应的编码信息,这样我们就不用每次都去运行程序来显示输出的东西了哦,也方便了我们对某些语句的验证,这个是比较赞的var与let前者为可变修饰符,后者为不可变从字面意思我们就可以很好的区分了常用的类型呢,跟其他语言基本相同啦,主要有几种:1.int类型2.Float,Double类型3.String类型4.Boolean类型当我们去声明一

  5. Swift调用OC和C

    Swift文件:main.swiftOC文件:Root.hRoot.mC函数文件:Fun.c桥接文件:工程名称-Bridging-Header.h

  6. OC调用Swift

    修改main.m文件OC文件:Root.hRoot.mSwift文件:Person.swift

  7. Swift 集合数据结构性能分析

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  8. Swift中的集合类数据结构

    在那种情况下,你将会需要一种基本的集合类数据结构。继续学习,你将会比较成熟的Cocoa数据结构与对应的纯Swift结构的性能。常见iOS数据结构iOS中三种最常用的数据结构是arrays,dictionaries和sets。除了在Swift和Objective-C中旧的Foundation框架中的数据结构,现在又有了新的仅支持Swift版本的数据结构与语言紧密结合在一起。Swift数组是同质的,意味着每一个Swift数组都只包含一种类型的对象。

  9. 红黑树

    1红黑树的性质1.1简介红黑树是一棵二叉搜索树,它在每个结点上增加了一个存储位来表示结点的颜色,可以是red或black。通过对任何一条从根到叶子结点的简单路径上各个结点的颜色进行约束,红黑树确保没有一条路径会比其他路径长出2倍,因而近似于平衡的。如下图表示就是一颗红黑树,NIL为指向外结点的指针。由于这两个操作对树做了修改,结果可能违反红黑性质。

  10. 11.Swift 中的类和结构体

    举例来说,以下情境中适合使用结构体:1.几何形状的大小,封装一个width属性和height属性,两者均为Double类型。这次就讲到这里,下次我们继续

随机推荐

  1. 【数据结构】单调栈

    显然,每个发射站发来的能量有可能被0或1或2个其他发射站所接受,特别是为了安全,每个发射站接收到的能量总和是我们很关心的问题。由于数据很多,现只需要你帮忙计算出接收最多能量的发射站接收的能量是多少。输入输出格式输入格式:第1行:一个整数N;第2到N+1行:第i+1行有两个整数Hi和Vi,表示第i个人发射站的高度和发射的能量值。输入输出样例输入样例:34235610输出样例:7题解中有讲解代码实现

  2. BZOJ 1798 [Ahoi2009] Seq 维护序列seq [线段树+多重标记下传]【数据结构】

    有长为N的数列,不妨设为a1,a2,…Input第一行两个整数N和P。第二行含有N个非负整数,从左到右依次为a1,aN,。表示把所有满足t≤i≤g的ai改为ai×c。操作2:“2tgc”。同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。Output对每个操作3,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。SampleInput7431234567512553242379313347SampleOutput2358HINT初始时数列为。对第5次操作,和为29+34+15+16=

  3. 陈越《数据结构》第一讲 基本概念

    陈越《数据结构》第一讲基本概念1什么是数据结构1.1引子例子:如何在书架上摆放图书?数据结构是:1.数据对象在计算机中的组织方式;2.数据对象必定与一系列加在其上的操作相关联;3.完成这些操作所用的方法就是算法。抽象数据类型数据类型-数据对象集;-数据集合相关联的操作集。抽象-与存放数据的机器无关;-与数据存储的物理结构无关;-与实现操作的算法和编程语言均无关。

  4. 陈越《数据结构》第二章 线性结构

    表中元素个数称为线性表的长度;线性表没有元素时,称为空表;表起始位置称表头,表结束位置称表尾。插入和删除操作只能在链栈的栈顶进行。

  5. 【数据结构】

    非线性结构:线性结构的元素之间具有线性关系,非线性结构中的元素之间不再是序列的关系,他们呈现的是更复杂的层次关系,即一个数据元素有且仅有一个直接前驱,但可有另个或者多个直接后继,显然比序列关系复杂常见非线性结构:树,图散列表PHP中的hashtable就是哈希表就是由数组和链表组成,一个长度为16的数组中,每个元素存储的是一个链表的头结点。

  6. 【数据结构】【C++STL】FIFO队列&amp;优先队列

    首先都需要打头文件queueFIFO队列是先进先出的就好像排队一样STL定义FIFO队列优先队列的话是有优先级存在的STL定义优先队列定义方式都是大根堆FIFO队列和优先队列都有一些操作COYG

  7. 【数据结构】 堆

    自底向上://增加/减少已有节点值Heap_Increase_Key//向堆插入新的节点HeapInsert自顶向下://替换堆顶后,维持堆函数KeepHeap//弹出堆顶函数Pop

  8. 【数据结构】链表

    线性表的顺序存储结构有存储密度高及能够随机存取等优点,但存在以下不足:线性表的链式存储(单链表)的实现单向循环链表的实现

  9. 伸展树(SPLAY)个人总结+模板 [平衡树]【数据结构】【模板】

    前言最近3个月内,无论是现场赛还线上赛中SPLAY出现的概率大的惊人啊啊啊!!!然而不会的我就GG了,同时发现大家都会SPLAY,,,,然后就学习了一波。——————————————————————————-附上整体代码-md贴上来太卡了,去题解里看吧维护序列的维护一堆数的

  10. BZOJ 1895 &amp; POJ 3580 supermemo [SPLAY]【数据结构】

    Ay}Ttimes.Forexample,performing“REVOLVE242”on{1,5}INSERTxP:insertPafterAx.Forexample,performing“INSERT24”on{1,5}DELETEx:deleteAx.Forexample,performing“DELETE2”on{1,5}MINxy:querytheparticipantwhatistheminimumnumberinsub-sequence{Ax…Ay}.Forexample,thecorrec

返回
顶部