红黑树的实现
来源:互联网 发布:js小数点后最多写两位 编辑:程序博客网 时间:2024/05/29 14:58
红黑树(RBT)的定义:它或者是一颗空树,或者是具有一下性质的二叉查找树:
1.节点非红即黑。
2.根节点是黑色。
3.所有NULL结点称为叶子节点,且认为颜色为黑。
4.所有红节点的子节点都为黑色。
5.从任一节点到其叶子节点的所有路径上都包含相同数目的黑节点。
上面的定义理解起来有点费解,所以我总结了以下三点,只要满足以下三点就可以是红黑树了。
1.根节点必须是黑树
2.红树不能连续链接,黑树可以。
3.每条路径上黑树的个数必须是相同的。
插入操作(Insert)
由于性质的约束:插入点不能为黑节点,应插入红节点。因为你插入黑节点将破坏性质5,所以每次插入的点都是红结点,但是若他的父节点也为红,那就会破坏了性质4,所以要做一些“旋转”和一些节点的变色!另外为叙述方便,我们给要插入的节点分别定义如下:
N(红色),父节点为P,祖父节点为G,叔节点为U
下边将一一列出所有插入时遇到的情况:
情况一:该树为空树,直接插入根结点的位置,违反性质1,把节点颜色有红改为黑即可。
情况二:插入节点N的父节点P为黑色,不违反任何性质,无需做任何修改。
情况三:N为红,P为红,(祖节点一定存在,且为黑,下边同理)U也为红,这里不论P是G的左孩子,还是右孩子;不论N是P的左孩子,还是右孩子。如下图所示:
操作:先把P和U变为黑色,然后G变为红色
情况四:N为红,P为红,U为黑,P为G的左孩子,N为P的左孩子(或者P为G的右孩子,N为P的左孩子;反正就是同向的)如下图所示:
操作:将P变黑,G变红,然后以p为轴右旋
情况五:N为红,P为红,U为黑,P为G的左孩子,N为P的右孩子(或者P为G的右孩子,N为P的左孩子;反正两方向相反)。如下图所示:
操作:首先以P为轴左旋,然后将p和N指向的地址交换,然后就转换为情况四
代码如下:
数据结构定义如下:
enum Colour{RED,BLACK,};template<class K, class V>struct RBTreeNode{// 链接结构RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;// Key/ValueK _key;V _value;// 颜色Colour _col;RBTreeNode(const K& key, const V& value, Colour col = RED):_left(NULL), _right(NULL), _parent(NULL), _col(col), _key(key), _value(value){}};操作代码如下:
template<class K, class V>class RBTree{typedef RBTreeNode<K, V> Node;public:RBTree():_root(NULL){}bool Insert(const K& key, const V& value){//1.树为空if (_root == NULL){_root = new Node(key, value, BLACK);return true;}// 查找位置,插入节点Node* parent = NULL;Node* cur = _root;while (cur){if (cur->_key > key){parent = cur;cur = cur->_left;}else if (cur->_key < key){parent = cur;cur = cur->_right;}else{return false;}}cur = new Node(key, value, RED);if (parent->_key < key){parent->_right = cur;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}// 调整while (cur != _root && parent->_col == RED) //这两个条件说明了cur一定存在parent 和 grandfather{Node* grandfather = parent->_parent;if (parent == grandfather->_left){Node* uncle = grandfather->_right;// case1if (uncle && uncle->_col == RED) //uncle存在且uncle的颜色为红色{parent->_col = uncle->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = cur->_parent;}else // case2/case3 //uncle不存在 或 uncle存在但颜色为黑色{// case3->case2if (cur == parent->_right){_RotateL(parent); //先左旋在交换swap(cur, parent); //交换cur和parent的地址,此时cur指向parent的地址,parent指向cur的地址}grandfather->_col = RED;parent->_col = BLACK;_RotateR(grandfather); //在右旋}}else //parent == grandfather->_right{Node* uncle = grandfather->_left;if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = cur->_parent;}else{if (cur == parent->_left){_RotateR(parent);swap(cur, parent);}grandfather->_col = RED;parent->_col = BLACK;_RotateL(grandfather);}}}_root->_col = BLACK;return true;}void _RotateL(Node* parent)//左旋转{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;//修改指针(1)if (subRL)subRL->_parent = parent;subR->_left = parent; //修改指针(2)subR->_parent = parent->_parent;parent->_parent = subR;if (subR->_parent == NULL){_root = subR;}else{if (subR->_parent->_key > subR->_key){subR->_parent->_left = subR;//修改指针(3)}else{subR->_parent->_right = subR;}}}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;parent->_parent = subL;if (subL->_parent == NULL){_root = subL;}else{if (subL->_parent->_key > subL->_key){subL->_parent->_left = subL;}else{subL->_parent->_right = subL;}}}void InOrder(){return _InOrder(_root);}void _InOrder(Node* root){if (root == NULL){return;}_InOrder(root->_left);cout << root->_key << " ";_InOrder(root->_right);}protected:Node* _root;};
以上仅是红黑树的插入操作和打印操作,希望以上代码能帮助到想学编程的童鞋。
- 红黑树的实现源码
- 红黑树的实现分析
- 红黑树的C++实现
- 红黑树的实现
- 红黑树的实现源码
- 红黑树的Java实现
- 红黑树的插入实现
- 红黑树的实现源码
- C++ 红黑树的实现
- 红黑树的C++实现
- 红黑树的实现
- 红黑树的JAVA实现
- 红黑树的实现代码
- 红黑树的实现
- 红黑树的代码实现
- 红黑树的C++实现
- 红黑树的C实现
- Golang实现的红黑树
- GitHub 流行开源库
- 【Android】Activity之间的切换效果定义
- hrbust 1687/哈理工oj 1687 买房子【二维最短路+SPFA】
- 博客开通
- 位运算-Single Number II(给定一个数组,除了一个数字出现一次,其他都出现三次,求出现一次的数)
- 红黑树的实现
- mysql存储过程中使用事务
- 属性与方法. this、super关键字
- 简单实现倒数读秒
- 剑指offer34--两个链表第一个公共结点
- 利用python进行数据分析-数据聚合与分组运算1
- ==和equals怎么用?java如何判断相等
- cin、cin.get()、cin.getline()、getline()、gets()等函数的用法
- UrlRewriteFilter