红黑树
来源:互联网 发布:开淘宝店挣钱么 编辑:程序博客网 时间:2024/06/04 17:58
1.红黑树简介
红黑树(Red Black Tree) 是一种自平衡二叉查找树,红黑树和AVL树类似,都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。它虽然是复杂的,但它的最坏情况运行时间也是非常良好的,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。
红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:
性质1. 节点是红色或黑色。
性质2. 根节点是黑色。
性质3 每个叶节点(NIL节点,空节点)是黑色的。
性质4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
性质5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
这些约束强制了红黑树的关键性质: 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。结果是这个树大致上是平衡的。因为操作比如插入、删除和查找某个值的最坏情况时间都要求与树的高度成比例,这个在高度上的理论上限允许红黑树在最坏情况下都是高效的,而不同于普通的二叉查找树。
2.代码实现
#ifndef RBT_H#define RBT_H#include <iostream>using namespace std;enum Color{ RED, BLACK};template<typename K, typename V>struct Node{ K key; V val; int N; Color color; Node<K, V>* left; Node<K, V>* right; Node() { this->left = NULL; this->right = NULL; } Node(K key, V val) { this->key = key; this->val = val; this->N = 1; this->color = RED; this->left = NULL; this->right = NULL; }};template<typename K, typename V>class RBT{public: RBT(); ~RBT(); V Getval(const K& key) const; Node<K, V>* Insert(const K& key, const V& val); void Del(int arr[], int index, const K& key); bool contain(const K& key) const; int size() const; void clean(); K minKey() const; K MaxKey() const; K CountLevel() const; void pretree() const; void midtree() const; void lasttree() const;protected: Node<K, V>* root; Node<K, V>* Roleft(Node<K, V>* node); Node<K, V>* Roright(Node<K, V>* node); void filpNode(Node<K, V>* node); void ReFilpNode(Node<K, V>* node); Node<K, V>* fixNode(Node<K, V>* node); Node<K, V>* Insert(Node<K, V>* node, const K& key, const V& val); V Getval(Node<K, V>* node, const K& key) const; bool contain(Node<K, V>* node, const K& key) const; Node<K, V>* del(int arr[], int index, Node<K, V>* node, const K& key); void clean(Node<K, V>* node); int size(Node<K, V>* node) const; K minKey(Node<K, V>* node) const; K MaxKey(Node<K, V>* node) const; K CountLevel(Node<K, V>* node) const; bool isRed(Node<K, V>* node); void pretree(Node<K, V>* node) const; void midtree(Node<K, V>* node) const; void lasttree(Node<K, V>* node) const;};//构造 析构函数template<typename K, typename V>RBT<K, V>::RBT(){ this->root = NULL;}template<typename K, typename V>RBT<K, V>::~RBT(){ clean(this->root);}/********************************************************************函数名称: isRed函数参数: @node 节点指针函数说明: 判断节点的颜色返回值: 成功返回true 失败返回false*********************************************************************/template<typename K, typename V>bool RBT<K, V>::isRed(Node<K, V>* node){ if (node == NULL || node->color == BLACK) return false; else return true;}/********************************************************************函数名称: Insert函数说明: 放入键值对<key,value> 若存在则将原有的value替换成新的value返回值: 无*********************************************************************/template<typename K, typename V>Node<K,V>* RBT<K, V>::Insert(const K& key, const V& val){ return this->root = Insert(this->root, key, val);}template<typename K, typename V>Node<K, V>* RBT<K, V>::Insert(Node<K, V>* node, const K& key, const V& val){ if (node == NULL) return new Node<K, V>(key, val); if (key > node->key) node->right = Insert(node->right, key, val); else if (key < node->key) node->left = Insert(node->left, key, val); else node->val = val; if (isRed(node->right) && !isRed(node->left)) node = Roleft(node); if (node->left != NULL && isRed(node->left) && isRed(node->left->left)) node = Roright(node); if (isRed(node->left) && isRed(node->right)) filpNode(node); node->N = size(node->left) + size(node->right) + 1; return node;}/********************************************************************函数名称: Getval函数说明: 获取指定key的value返回值: value*********************************************************************/template<typename K, typename V>V RBT<K, V>::Getval(const K& key) const{ return Getval(this->root, key);}template<typename K, typename V>V RBT<K, V>::Getval(Node<K, V>* node, const K& key) const{ if (node == NULL) return NULL; if (key > node->key) return Getval(node->right, key); else if (key < node->key) return Getval(node->left, key); else return node->val;}/********************************************************************函数名称: clean函数说明: 清空表返回值: 无*********************************************************************/template<typename K, typename V>void RBT<K, V>::clean(){ clean(this->root); this->root = NULL;}template<typename K, typename V>void RBT<K, V>::clean(Node<K, V>* node){ if (node == NULL) return; clean(node->left); clean(node->right); delete node;}/********************************************************************函数名称: size函数说明: 无返回值: 红黑树节点个数*********************************************************************/template<typename K, typename V>int RBT<K, V>::size() const{ return size(this->root);}template<typename K, typename V>int RBT<K, V>::size(Node<K, V>* node) const{ if (node == NULL) return 0; return size(node->right) + size(node->left) + 1;}/********************************************************************函数名称: Del函数说明: 删除某个key返回值: 无*********************************************************************/template<typename K, typename V>void RBT<K, V>::Del(int arr[], int index, const K& key){ this->root = del(arr, index, this->root, key);}int Delete(int arr[],int n, int x){ int p = 0, q = 0; //用p和q两个变量 while (q<n) //由q控制,扫描所有的元素 { if (arr[q] != x) { arr[p] = arr[q]; p++; } q++; } return p;}template<typename K, typename V>Node<K, V>* RBT<K, V>::del(int arr[],int index,Node<K, V>* node, const K& key){ RBT<int, int>RBT1; if (node == NULL) return NULL; Delete(arr, index, key); for (int i = 0; i < index - 1; i++) { RBT1.Insert(arr[i], i); } swap(this->root, RBT1.root); root->color = BLACK; return this->root;}/********************************************************************函数名称: prevtree/midtree/lasttree函数说明: 遍历*********************************************************************/template<typename K, typename V> //前序遍历void RBT<K, V>::pretree() const{ pretree(this->root);}template<typename K, typename V>void RBT<K, V>::pretree(Node<K, V>* node) const{ if (node != NULL) { cout << node->key << '\t'; if (node->color == BLACK) { cout << "黑色" << endl; } else { cout << "红色" << endl; } pretree(node->left); pretree(node->right); }}template<typename K, typename V> //中序遍历void RBT<K, V>::midtree()const{ midtree(this->root);}template<typename K, typename V>void RBT<K, V>::midtree(Node<K, V>* node) const{ if (node != NULL) { midtree(node->left); cout << node->key << '\t'; if (node->color == BLACK) { cout << "黑色" << endl; } else { cout << "红色" << endl; } midtree(node->right); }}template<typename K, typename V> //后序遍历void RBT<K, V>::lasttree()const{ lasttree(this->root);}template<typename K, typename V>void RBT<K, V>::lasttree(Node<K,V>* node) const{ if (node != NULL) { lasttree(node->left); lasttree(node->right); cout << node->key << '\t'; if (node->color == BLACK) { cout << "黑色" << endl; } else { cout << "红色" << endl; } }}/********************************************************************函数名称: contain函数说明: 是否包含key返回值: 包含返回true 不包含返回false*********************************************************************/template<typename K, typename V>bool RBT<K, V>::contain(const K& key) const{ return contain(this->root, key);}template<typename K, typename V>bool RBT<K, V>::contain(Node<K, V>* node, const K& key) const{ if (node == NULL) return false; if (key > node->key) Getval(node->right, key); else if (key < node->key) Getval(node->left, key); else return true;}/********************************************************************函数名称: Roleft函数参数: 需要旋转的节点指针函数说明: 将右节点旋转到左边并设置为红色返回值: 旋转后的树根指针*********************************************************************/template<typename K, typename V>Node<K, V>* RBT<K, V>::Roleft(Node<K, V>* node){ Node<K, V>* right = node->right; node->right = right->left; right->left = node; right->color = node->color; node->color = RED; node->N = size(node->left) + size(node->right) + 1; right->N = size(right->left) + size(right->right) + 1; return right;}/********************************************************************函数名称: Roright函数参数: 需要旋转的节点指针函数说明: 将左节点旋转到右边并设置为红色返回值: 旋转后的树根指针*********************************************************************/template<typename K, typename V>Node<K, V>* RBT<K, V>::Roright(Node<K, V>* node){ Node<K, V>* left = node->left; node->left = left->right; left->right = node; left->color = node->color; node->color = RED; node->N = size(node->left) + size(node->right) + 1; left->N = size(left->left) + size(left->right) + 1; return left;}/********************************************************************函数名称: flipNode函数参数: 节点指针函数说明: 将节点的左右子树的颜色变成黑色 同时节点颜色变成红色*********************************************************************/template<typename K, typename V>void RBT<K, V>::filpNode(Node<K, V>* node){ node->color = RED; node->left->color = BLACK; node->right->color = BLACK;}/********************************************************************函数名称: ReFilpNode函数参数: @node 节点指针函数说明: 反向翻转节点和子节点的颜色 将节点颜色变成黑色 子节点红色返回值: 无*********************************************************************/template<typename K, typename V>void RBT<K, V>::ReFilpNode(Node<K, V>* node){ node->color = BLACK; node->left->color = RED; node->right->color = RED;}/********************************************************************函数名称: fixRedNode函数参数: @node 节点指针函数说明: 修复反向反转后节点 node->right->left 为红色的情况返回值:*********************************************************************/template<typename K, typename V>Node<K, V>* RBT<K, V>::fixNode(Node<K, V>* node){ node->right = Roright(node->right); node = Roleft(node); return node;}/********************************************************************函数名称: minKey函数参数: 无函数说明: 返回表中最小的key返回值: key*********************************************************************/template<typename K, typename V>K RBT<K, V>::minKey() const{ return minKey(this->root);}template<typename K, typename V>K RBT<K, V>::minKey(Node<K, V>* node) const{ if (node->left == NULL) return node->key; else minKey(node->left);}/********************************************************************函数名称: MaxKey函数参数: 无函数说明: 返回红黑树中最大的key返回值: key*********************************************************************/template<typename K, typename V>K RBT<K, V>::MaxKey() const{ return MaxKey(this->root);}template<typename K, typename V>K RBT<K, V>::MaxKey(Node<K, V>* node) const{ if (node->right == NULL) return node->key; else MaxKey(node->right);}template<typename K, typename V>K RBT<K, V>::CountLevel() const{ return CountLevel(this->root);}template<typename K, typename V>K RBT<K, V>::CountLevel(Node<K, V>* node) const{ static int count = 0; if (node) { if (node->left == NULL&&node->right == NULL) ++count; CountLevel(node->left); CountLevel(node->right); } return count;}#endifvoid test(){ RBT<int, int>RBT; int arr[11] = { 15, 6, 18, 3, 7, 17, 20, 2, 4, 13, 9 }; //int arr[5] = { 3, 5, 6, 2, 4 }; int index = sizeof(arr) / sizeof(arr[0]); Node<int, int>*ret = NULL; for (int i = 0; i < 11; i++) { ret = RBT.Insert(arr[i], i); } ret->color = BLACK; RBT.Del(arr, index, 3); RBT.midtree(); cout << endl; cout << RBT.minKey() << endl; cout << RBT.MaxKey() << endl; cout << RBT.Getval(6) << endl; cout << RBT.size() << endl; cout << RBT.CountLevel() << endl; cout << RBT.contain(6) << endl; RBT.pretree(); cout << endl; RBT.lasttree(); cout << endl;}int main(){ test(); system("pause"); return 0;}
3.红黑树和AVL树的比较
红黑树和AVL树都是高效的平衡二叉树, 增删查改的时间复杂度都是O(lg(N))
红黑树的不追求完全平衡, 保证最长路径不超过最短路径的2倍, 相对而言, 降低了旋转的要求, 所以性能会优于AVL树, 所以实际运用
中红黑树更多。