红黑树
来源:互联网 发布:道亨软件下载 编辑:程序博客网 时间:2024/06/06 20:10
红黑树:红黑树是一棵二叉搜索树,它在每个结点上增加了一个存储位来表示结点的颜色,可以是red或者black,通过对任何一条从根节点到叶子结点上的简单路径来约束,红黑树保证最长路径不超过最短路径的两倍,因而近视平衡。
性质:
1. 每个结点不是红色就是黑色
2. 根节点是黑色的
3. 如果一个根节点是红色的,则它的两个叶子结点是黑色的(没有两个连续
的红色结点)
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相
同数目的黑色结点(每条路径上黑色结点的数量相等)
5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)
插入的实现:
pCur为当前结点,parent为父亲结点,uncle为叔叔结点,grandpa为祖父结点
第一种情况:
pCur为红色,parent为红色,grandpa为黑色,uncle存在且为红色
做如下调整:parent改为黑色,grandpa改为红色,uncle改为黑色
第二种情况:
pCur为红色,parent为红色,grandpa为黑色,uncle不存在或存在且为黑色
做如下调整:grandpa的左孩子为parent,parent的左孩子为pCur时,对grandpa进行右单旋,parent改为黑色,grandpa改为红色;
grandpa的右孩子为parent,parent的右孩子为pCur时,对grandpa进行左单旋,parent改为黑色,grandpa改为红色;
第三种情况:
pCur为红色,parent为红色,grandpa为黑色,uncle不存在或存在且为黑色
做如下调整:grandpa的左孩子为parent,parent的右孩子为pCur时,先对parent进行左单旋并交换pCur和parent,然后对grandpa进行右单旋,pCurt改为黑色,grandpa改为红色;
grandpa的右孩子为parent,parent的左孩子为pCur时,先对parent进行右单旋并交换pCur和parent,然后对grandpa进行左单旋,pCurt改为黑色,grandpa改为红色;
完整代码如下:
rbt.cpp
#define _CRT_SECURE_NO_WARNINGS#include<iostream>#include<stdio.h>#include<stdlib.h>using namespace std;enum Color{ RED, BLACK};template<class K,class V>struct RBTreeNode{ RBTreeNode(const K& key,const V& value, Color color=RED) : _value(value) , _key(key) , _left(NULL) , _right(NULL) , _parent(NULL) , _color(color) {} K _key; V _value; RBTreeNode<K,V>* _left; RBTreeNode<K, V>* _right; RBTreeNode<K, V>* _parent; Color _color;};template<class K, class V>class RBTree{ typedef RBTreeNode<K, V>Node;public: RBTree() :_pRoot(NULL) {} //插入 bool Insert(const K& key,const V& value) { if (NULL == _pRoot) { _pRoot = new Node(key, value); return true; } //寻找插入位置 Node* pCur = _pRoot; Node* parent = NULL; while (pCur) { if (pCur->_key < key) { parent = pCur; pCur = pCur->_right; } else if (pCur->_key>key) { parent = pCur; pCur = pCur->_left; } else { return false; } } //插入结点 pCur = new Node(key, value); if (parent->_key > key) { parent->_left=pCur; pCur->_parent = parent; } else { parent->_right=pCur; pCur->_parent = parent; } while (parent != _pRoot && parent->_color == RED) { Node* grandpa = parent->_parent; if ( grandpa->_left==parent) { Node* uncle = grandpa->_right; { Node* uncle = grandpa->_right; //叔叔结点存在且为红色 if (uncle &&uncle->_color == RED) { parent->_color = BLACK; uncle->_color = BLACK; grandpa->_color = RED; //继续向上调整 pCur = grandpa; parent = pCur->_parent; } //叔叔结点不存在或叔叔结点存在为黑色 else { //pCur为parent的右孩子 if (pCur == parent->_right) { RotateL(parent); swap(pCur, parent); } parent->_color = BLACK; grandpa->_color = RED; RotateR(grandpa); break; } } } //parent=grandpa->_right else { Node* uncle = grandpa->_left; //叔叔结点存在且为红色 if (uncle &&uncle->_color == RED) { parent->_color = BLACK; uncle->_color = BLACK; grandpa->_color = RED; //继续向上调整 pCur = grandpa; parent = pCur->_parent; } else { //pCur为parent的左孩子 if (pCur == parent->_left) { RotateR(parent); swap(pCur, parent); } parent->_color = BLACK; grandpa->_color = RED; RotateL(grandpa); break; } } _pRoot->_color = BLACK; return true; } } //中序遍历 void Inorder() { return _Inorder(_pRoot); } //查找结点 bool Find(const K& key) { Node* pCur = _pRoot; if (pCur == NULL) return false; else { while (pCur) { if (pCur->_key < key) pCur = pCur->_right; else if (pCur->_key>key) pCur = pCur->_left; else return true; } } return true; } //判断是否平衡 bool IsBalance() { if (NULL == _pRoot) return true; if (_pRoot->_color == RED) return false; int k = 0; Node* pCur = _pRoot; while (pCur) { //记录其中一条路径黑色结点个数 if (pCur->_color == BLACK) ++k; pCur = pCur->_left; } //另一条路径黑色结点个数 int count = 0; return _IsBalance(_pRoot, k, count); } //左旋 void RotateL(Node* parent) { Node* subR = parent->_right; Node* subRL = subR->_left; subR->_left = parent; parent->_right = subRL; if (subRL) subRL->_parent = parent; Node* pparent = parent->_parent; if (NULL == pparent) { _pRoot = subR; subR->_parent = NULL; } else { if (pparent->_left == parent) pparent->_left = subR; else pparent->_right = subR; subR->_parent = pparent; } parent->_parent = subR; } //右旋 void RotateR(Node* parent) { Node* subL = parent->_left; Node* subLR = subL->_right; subL->_right = parent; parent->_left = subLR; if (subLR) subLR->_parent = parent; Node* pparent = parent->_parent; if (NULL == pparent) { _pRoot = subL; subL->_parent = NULL; } else { if (pparent->_left == parent) pparent->_left = subL; else pparent->_right = subL; subL->_parent = pparent; } parent->_parent = subL; } void _Inorder(Node* pRoot) { if (NULL == pRoot) return ; _Inorder(pRoot->_left); cout << pRoot->_key << "->"; _Inorder(pRoot->_right); } bool _IsBalance(Node* pRoot, int k, int count) { if (NULL == pRoot) return true; if (pRoot->_color == RED) { if (pRoot->_parent&&pRoot->_parent->_color == RED) return false; } else count++; if (pRoot->_left == NULL&&pRoot->_right == NULL) { //比较两条路径黑色结点个数 if (k == count) return true; else return false; } return _IsBalance(pRoot->_left, k, count) && _IsBalance(pRoot->_left, k, count); }private: Node* _pRoot;};void test(){ RBTree<int, int> rbt; /*int array[] = {5,2,1,3,4,0,7,8,6}; int size = sizeof(array) / sizeof(array[0]); for (int i = 0; i < size; i++) { rbt.Insert(array[i],i); }*/ rbt.Insert(5, 5); rbt.Insert(2, 2); rbt.Insert(1, 1); rbt.Insert(3, 3); rbt.Insert(4, 4); rbt.Insert(0, 0); rbt.Insert(7, 7); rbt.Insert(8, 8); rbt.Insert(6, 6); rbt.Inorder(); cout << "\n"; cout<<rbt.Find(5)<<endl; cout << "\n"; cout << rbt.IsBalance() << endl;}int main(){ test(); system("pause"); return 0;}
- 红黑树
- 红黑树
- 红黑树
- 红黑树
- 红黑树
- 红黑树
- 红黑树
- 红黑树
- 红黑树
- 红黑树
- 红黑树
- 红黑树
- 红黑树
- 红黑树
- 红黑树
- 红黑树
- 红黑树
- 红黑树
- java Map及Map.Entry详解
- JS获取浏览器高度和宽度
- uva11995基础数据结构
- Java网络编程——第七章 URLConnection
- 测试,待更新
- 红黑树
- (5)关卡编辑器之视口
- 数据库基础
- java调用shell脚本、windows命令
- 数据结构与算法(20)——二叉树习题三
- AVAssetWriter写h264数据
- 6.Oracle:安装oracle11g INS-30131执行安装程序验证所需的初始设置失败的解决方法
- 自己实现的一个简易Spring框架(IoC+AOP)
- Android ADB