RBTree(红黑树)
来源:互联网 发布:华润儿童漆怎么样知乎 编辑:程序博客网 时间:2024/05/29 03:35
红黑树
红黑树(Red Black Tree)和AVL树类似,都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡。
红黑树是一颗二叉搜索树,它的每一个节点增加了一个存储位用来表示颜色,可以是Red也可以是Black,通过对任意一条根到叶子节点的颜色来约束,红黑树保证最长路径是最短路径的两倍,因此近似平衡;
红黑树的性质:
1:每个节点不是红色就是黑色
2:根节点是黑色
3:如果一个节点时红,则它两个子节点是黑色的(没有连续的红色)
4:对每个节点,从该节点到其后代的所有叶子节点的简单路径,均有相同数目的黑节点(每条路径的黑色节点色数目相同)
两者的差别:AVL树是完全平衡树,更接近满二叉树,因此它的时间复杂度是O(lgN),在二叉树插入删除时旋转多,维护起来比较麻烦,但相比更直观。而RBT树是近似平衡树,时间复杂度是2O(log n),旋转较少,相对维护起来比较简单,但是相比更抽象。相对来说运用最多的还是RBTree。
红黑树的应用: 在C++ STL中,很多部分都运用了红黑树包括:Linux内核,java c# 还有(包括set, multiset, map, multimap)应用了红黑树的变体(SGI STL中的红黑树有一些变化,这些修改提供了更好的性能,以及对set操作的支持)等等。
下面就是节点的颜色转换以及旋转的情况:
在此只展示了parent为孩子的情况,parent为右孩子情况类似。
具体实现源码如下:
#include <math.h>#include <iostream>using namespace std;enum colour{ BLACK, RED,};template<class K, class V>struct RBTreeNode{ K _key; V _val; colour _col; RBTreeNode<K, V>* _left; RBTreeNode<K, V>* _right; RBTreeNode<K, V>* _parent; int _bf; RBTreeNode(const K& key, const V& value) :_left(NULL) , _right(NULL) , _parent(NULL) , _key(key) , _val(value) , _bf(0) , _col(RED) {}};template<class K, class V>class RBTree{ typedef RBTreeNode<K, V> Node;public: RBTree() :_root(NULL) {} ~RBTree() {} 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 (key > parent->_key) { parent->_right = cur; cur->_parent = parent; } else { parent->_left = cur; cur->_parent = parent; } while (parent && parent->_col==RED) { Node* grandparent = parent->_parent; if (grandparent->_left==parent) //父亲在左边 { Node* uncle = grandparent->_right; if (uncle&&uncle->_col==RED) { parent->_col = BLACK; uncle->_col = BLACK; grandparent->_col = RED; cur = grandparent; //向上调整 parent = cur->_parent; // } else //叔叔不存在或者叔叔为黑,需要旋转 { if (cur==parent->_right) { RotateL(parent); swap(parent,cur); } RotateR(grandparent); parent->_col = BLACK; grandparent->_col = RED; break; } } else //parent = grandparent->_right; { Node* uncle = grandparent->_left; if (uncle&&uncle->_col == RED) { parent->_col = BLACK; uncle->_col = BLACK; grandparent->_col = RED; cur = grandparent; //向上调整 parent = cur->_parent; // } else //叔叔不存在或者叔叔为黑,需要旋转 { if (cur == parent->_left) { RotateR(parent); swap(parent, cur); // 若cur在parent的左,cur->_key < parent->_key,旋转后必须交换才符合_key值得排布规则。 } RotateL(grandparent); parent->_col = BLACK; grandparent->_col = RED; } } } _root->_col = BLACK; return true; } bool Isbalance() { if (_root==NULL) { return true; } if (_root->_col==RED) { return false; } int Blacknum = 0; Node* left = _root; while (left) //遍历任意一边,计算出黑色节点的个数,作为一个基准,将此数与其他路上的书做较,只要不相等就可以说明此树不是平衡红黑树 { if (left->_col==BLACK) { Blacknum++; } left = left->_left; } int num = 0; return _IsBalance(_root, Blacknum, num); } bool _IsBalance(Node* root, const int Blacknum, int num) { if (root == NULL) { if (num != Blacknum) { cout << "黑节点个数不等" << endl; return false; } else { return true; } } if (root->_col == BLACK) { num++; } if ((root->_col == RED) && (root->_parent->_col == RED)) { cout << root->_key << " " << root->_parent->_key << " " << endl; return false; } return _IsBalance(root->_left, Blacknum, num) && _IsBalance(root->_right, Blacknum, num); } void RotateL(Node* parent)// 左单旋 { Node* subR = parent->_right; Node* subRL = subR->_left; parent->_right = subRL; if (subRL) //开始旋转 { subRL->_parent = parent; } // subR->_left = parent; subR->_parent = parent->_parent; Node* ppnode = parent->_parent; parent->_parent = subR;///////////////// if (ppnode == NULL) { _root = subR; subR->_parent = NULL; } else if (parent == ppnode->_left) { ppnode->_left = subR; } else { ppnode->_right = subR; } subR->_parent = ppnode; } void RotateR(Node* parent) { Node* subL = parent->_left; Node* subLR = subL->_right; parent->_left = subLR; if (subLR) { subLR->_parent = parent; } subL->_right = parent; subL->_parent = parent->_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 InOrder() { _InOrder(_root); cout << endl; }protected: void _InOrder(Node* root) { if (root == NULL) { return; } _InOrder(root->_left); cout << root->_key << " "; _InOrder(root->_right); }private: Node* _root;};void Test(){ int a[] = { 5, 3, 4, 1, 7, 8, 2, 6, 0, 9 }; //int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 }; //int a[] = {2,3,1,4,5}; //int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 }; RBTree<int, int> t; for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); i++) { //t.Insert(a[i], i); t.Insert(a[i],i); cout << t.Isbalance()<< endl; } t.InOrder();}
阅读全文
1 1
- 红黑树(RBtree)
- 数据结构-红黑树(RBTree)
- 红黑树(RBTree)
- RBTree(红黑树)
- 红黑树(RBTree)的实现
- 红黑树-RBTree
- RBTree红黑树
- RBTree----红黑树
- RBTree(红黑树)
- 红黑树--RBTree
- 红黑树【RBTree】
- 算法编程_红黑树(RBTree)
- 红黑树(RBTree)之插入结点图解
- 红黑树(RBTree)之删除结点图解
- 二叉搜索树—RBTree(红黑树)
- Linux内核之rbtree(红黑树)
- RBTree(红黑树的简单实现)
- RBTree-红黑树的实现
- KK录像机怎么用?KK录像机使用方法介绍
- 基于FPGA的驱控一体控制器及控制系统
- Day6:磁盘配额与高级文件系统管理
- 常量池
- oracle导出导入数据和创建用户以及授权命令
- RBTree(红黑树)
- 从键盘输入n名学生数据,转存到磁盘文件,然后回显
- Unity对象旋转功能
- Mybatis--入门
- 《视觉SLAM十四讲》书籍图片资源
- 好用的天气插件
- Installation failed with message Failed to establish session.
- js点击当前元素增加样式
- 深入理解AJAX系列第四篇--跨域问题