C++实现红黑树
来源:互联网 发布:淘宝旧版本5.9.0下载 编辑:程序博客网 时间:2024/06/13 22:08
红黑树简介
红黑树是一个高效的平衡搜索树,保证最长路径不超过最短路径的两倍,因而近似平衡,保证了高度,也就保证了效率。增删查改时间复杂度都是O(logN)
性质:
- 每个结点不是红色就是黑色的。
- 根结点是黑色的。
- 如果一个结点是红色的,则它的两个子节点是黑色的(没有连续的红结点)
- 对于每个结点,从该结点到其所有后代叶节点的简单路径上,均包含相同数目的黑色结点(每条路径的黑色节点的数目相等)
- 每个叶子结点都为黑色(此处叶子结点是空结点)
这几条规则保证了红黑树最长路径不超过最短路径的两倍(给个极端情况全黑色,然后在结点之间插入红色结点,即可得到结论)
结点的实现
三叉链实现RBtree,用KV存储结构,最后用枚举包含了相应的颜色。
树的实现
共有成员为空的构造函数,插入函数
私有成员为根,
红黑树的插入
为什么插入结点的颜色为红色好?
如果插入结点为黑色首先违背了第四条规则,每条路径黑色结点数目相同,虽然可以调整但是难调,我们原则上的保持第四条规则,所以选择插入红色节点。
方法:
首先判断是否为空树,接着找到插入结点,根据插入结点的情况来调整。 cur为插入结点,g为组父节点,p是父亲结点,u是叔叔结点
1. 如果插入结点为根结点,则直接插入,并且将根结点赋值为黑色。
2. 如果插入结点的父节点为黑色结点,那么直接插入。
3. 如果插入结点的父节点为红色结点,那么再次插入时,必然会有两个红色结点相连接,此时需要调整。
叔叔结点的情况和调整有关,叔叔的情况有以下几种:
叔叔存在且为红色
叔叔不存在
叔叔为黑色
插入分为三种情况
- 组父节点为黑色,父节点和叔叔结点为为红色,插入节点的为红色。
此种情况下父亲结点和叔叔结点变为黑色,祖父结点变为红色,如果祖父结点是根结点则不影响,如果祖父结点不是根结点,则需要向上更新, 祖父结点为黑色,父亲结点为红色,叔叔结点(不存在或者为黑色),插入结点为红色。(单旋)
- 第一种情况,叔叔不存在,cur为新增结点,
- 第二种情况,叔叔存在且为黑色,parent的一边C一定存在且为黑色,cur为红色结点,cur此时不是新插入的结点,cur存在左右孩子,并且cur原先为黑色((cur此时左右为黑色吗?))
此时旋转来调整结点,观察p和cur均为左孩子,此时右单旋,p和cur均为右孩子,此时左单旋。
- 祖父结点为黑色,父亲结点为红色,叔叔结点(不存在或者为黑色),插入结点为红色。(双旋)
- 第一种情况:u存在并且一定为黑色,cur不是新插入的结点,cur存在左右孩子,并且cur原先为黑色。
- 第二种情况:u不存在,cur一定为新插入的结点。
实现代码如下
#include <iostream>#include <assert.h>using namespace std;enum Colour{ RED, BLACK,};template <class K,class V>struct RBTreeNode{ RBTreeNode* _left; RBTreeNode* _right; RBTreeNode* _parent; K _key; V _value; Colour _col; RBTreeNode(const K& key = K(), const V& value = V(), const Colour& color = RED) :_left(NULL) , _right(NULL) , _parent(NULL) , _key(key) , _value(value) , _col(color) {}};template <class K,class V>class RBTree{ typedef RBTreeNode<K, V> Node;public: RBTree() :_root(NULL) {} ~RBTree() { //if (_root) // _root = _Destroy(_root); } RBTree(const RBTree<K, V>& rb) { if (this != &rb) _root = _Copy(_root); } RBTree<K, V> operator=(const RBTree<K, V>& rb) { if (*this != rb) { Node* tmp = _Copy(rb->_root); _root = _Destroy(_root); _root = tmp; } return *this; } bool Insert(const K& key, const V& value) { if (_root == NULL) { _root = new Node(key, value); _root->_col = BLACK; return true; } Node* pCur = _root; Node* pParent = NULL; while (pCur) { if (key < pCur->_key) { pParent = pCur; pCur = pCur->_left; } else if (key > pCur->_key) { pParent = pCur; pCur = pCur->_right; } else return false; } pCur = new Node(key, value); if (key < pParent->_key) pParent->_left = pCur; else pParent->_right = pCur; pCur->_parent = pParent; //未调整到根节点且父节点还是红色 while (pCur != _root && pParent->_col == RED) { Node* grandfather = pParent->_parent; //先处理左边 if (grandfather->_left == pParent) { Node* uncle = pParent->_right; //叔叔存在且为红色 if (uncle && uncle->_col == RED) { pParent->_col = uncle->_col = BLACK; grandfather->_col = RED; pCur = grandfather; pParent = pCur->_parent; } //叔叔不存在或者叔叔为黑色 else { //pCur为pParent的右孩子 if (pParent->_right == pCur) { RotateL(pParent); std::swap(pCur, pParent); } //pCur为pParent的左孩子 else { RotateR(grandfather); grandfather->_col = RED; pParent->_col = BLACK; } } } //再处理右边的情况(与上述情况刚好位置相反) else { Node* uncle = grandfather->_left; //叔叔存在且为红 if (uncle && uncle->_col == RED) { pParent->_col = uncle->_col = BLACK; pCur->_col = RED; pCur = grandfather; pParent = pCur->_parent; } //叔叔不存在或者叔叔为黑色 else { //pCur为pParent的左孩子 if (pParent->_left == pCur) { RotateR(pParent); std::swap(pCur, grandfather); } //pCur为pParent的右孩子 else { RotateL(grandfather); grandfather->_col = RED; pParent->_col = BLACK; } } } } _root->_col = BLACK; return true; } void RotateR(Node* parent) { assert(parent); Node* subL = parent->_left; Node* subLR = subL->_right; parent->_left = subLR; if (subLR) subLR->_parent = parent; Node* pparent = parent->_parent; subL->_right = parent; parent->_parent = subL; if (pparent->_left == parent) { pparent->_left = subL; subL->_parent = pparent; } else if (pparent->_right == parent) { pparent->_right = subL; subL->_parent = pparent; } else { _root = subL; subL->_parent = NULL; } } void RotateL(Node* parent) { assert(parent); Node* subR = parent->_right; Node* subRL = subR->_left; parent->_right = subRL; if (subRL) subRL->_parent = parent; Node* pparent = parent->_parent; subR->_left = parent; parent->_parent = subR; if (pparent->_left = subR->_parent) { pparent->_left = subR; subR->_parent = pparent; } else if (pparent->_right = subR->_parent) { pparent->_right = subR; subR->_parent = pparent; } else { _root = subR; subR->_parent = NULL; } } bool IsBalance() { if (NULL == _root) return true; if (_root->_col == RED) return false; size_t count = 0; Node* cur = _root; while (cur) { if (cur->_col == BLACK) count++; cur = cur->_left; } size_t k = 0; _IsBalance(_root, count, k); } void InOrder() { _Inorder(_root); cout << endl; }private: bool _IsBalance(Node* _root, size_t count, size_t k) { if (_root == NULL) return true; if (_root->_parent&&_root->_col == _root->_parent->_col == RED) return false; if (_root->_col == BLACK) k++; if (_root->_left == NULL&&_root->_right == NULL) { if (count == k) return true; else return false; } return ((_IsBalance(_root->_left, count, k))&&(_IsBalance(_root->_right, count, k))); } void _Inorder(Node* Root) { if (Root) { _Inorder(Root->_left); cout << Root->_key << endl; _Inorder(Root->_right); } } Node* _Copy(Node* pRoot) { Node* pCur = pRoot; if (pCur) { pCur = new Node(pRoot->_key, pRoot->_value); pCur->_left= _Copy(pRoot->_left); pCur->_right = _Copy(pRoot->_right); } return pCur; } //销毁 Node* _Destory(Node* pRoot) { if (pRoot) { pRoot->_left = _Destory(pRoot->_left); pRoot->_right = _Destory(pRoot->_right); delete pRoot; pRoot = NULL; } return pRoot; } Node* _root;};
测试文件:
#include "RBtree.h"using namespace std;void test(){ RBTree<int, int> rb; int arr[] = { 10, 7, 8, 15, 5, 6, 11, 13, 12 }; for (size_t idx = 0; idx < sizeof(arr) / sizeof(arr[0]); ++idx) { rb.Insert(arr[idx], idx); } rb.InOrder(); if (rb.IsBalance()) cout << "是红黑树." << endl; else cout << "不是红黑树." << endl; rb.InOrder();}int main(){ test(); system("pause"); return 0;}
红黑树的应用
红黑树是一颗高效的二叉搜索树,用途很广,例如STL中set\map\unorder_map\unorder_set都运用到了红黑树。
阅读全文
0 0
- 红黑树C实现
- 红黑树<C语言实现>
- 红黑树C语言实现
- 红黑树-C语言实现
- 红黑树的C实现
- 红黑树(c实现)
- C语言实现红黑树
- 红黑树与C实现算法 - RedBlackTree.c
- 高效实现红黑树的插入--c实现
- 红黑树的实现(C++)
- 红黑树的一个C实现
- 红黑树及C语言实现
- 红黑树实现文件C语言
- 红黑树与C实现算法
- 红黑树的插入C实现
- 红黑树的c语言实现
- C/C++: 实现加减乘除。
- C实现C(3)
- 82岁“极客”老人将族谱摆上阿里云 还想去杭州云栖大会见马云
- HTC 部分“卖身” Google,11 亿美元的交易意味着什么?
- Mysql数据库的集群搭建
- iOS11今日凌晨正式更新,腾讯手机管家iOS防骚扰版开启垃圾短信过滤模式
- 将Sublime Text3添加到右键菜单中
- C++实现红黑树
- 郭明祺:Face ID会否用在所有iPhone上,就看你们了!
- 甲骨文 CEO 赫德开炮亚马逊:AWS 的基础设施已过时,传统数据库用户不会转投亚马逊
- 微信悄悄提升1对1红包额度,520元帮你情人节表真心
- 金山放权,傅盛终于可以放心追逐他“不靠谱”的梦想
- VR也救不了HTC,曾经的安卓老大连续7个季度出现亏损
- 最少拦截系统
- 关于Python3的collections.namedtuple和functools.namedtuple的探讨
- 清理字符串中的数字Java实现