1. 红黑树
1.1 红黑树的概念
红黑树,是一种二叉搜索树,但在每个节点上增加一个存储为表示节点的颜色,可以使Red或Black。通过对任何一条从根到叶子的路径上各个节点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的。
1.2 红黑树的性质
1.每个节点不是红色就是黑色
2.根节点是黑色的
3.如果一个节点是红色的,则它的两个孩子节点是黑色的
4.对于每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点
5.每个叶子节点都是黑色的(此处的叶子节点指的是空节点)
1.3 红黑树节点的定义
enum Color
{RED,BLACK
};template <class K, class V>
struct RBTreeNode
{pair<K, V> _kv;//节点内的数据采用Key、Value形式RBTreeNode<K, V>* _left;//该节点的左孩子RBTreeNode<K, V>* _right;//该节点的右孩子RBTreeNode<K, V>* _parent;//该节点的双亲Color _col;RBTreeNode(const pair<K, V>& kv):_kv(kv), _left(nullptr), _right(nullptr), _parent(nullptr){}
};
1.4 红黑树的定义(代码不包含删除)
template <class K, class V>
class RBTree
{
public:typedef RBTreeNode<K, V> Node;RBTree() = default;RBTree(const RBTree<K, V>& t){_root = Copy(t._root);}RBTree<K, V>& operator=(RBTree<K, V> t){swap(_root, t._root);return *this;}~RBTree(){Destory(_root);_root = nullptr;}bool insert(const pair<K, V>& kv){if (_root == nullptr){_root = new Node(kv);return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(kv);cur->_col = RED;if (parent->_kv.first < kv.first){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;while (parent && parent->_col == RED){Node* grandfather = parent->_parent;if (parent == grandfather->_left){Node* uncle = grandfather->_right;if (uncle && uncle->_col == RED)//如果叔叔存在且为红{parent->_col = BLACK;uncle->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = cur->_parent;}else//叔叔不存在或叔叔不存在且为黑{if (cur == parent->_left){RotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{RotateL(parent);RotateR(grandfather);cur->_col = BLACK;grandfather->_col = RED;}}break;}else{Node* uncle = grandfather->_left;if (uncle && uncle->_col == RED){uncle->_col = parent->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = cur->_parent;}else{if (parent->_right == cur){RotateL(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{RotateR(parent);RotateL(grandfather);cur->_col = BLACK;grandfather->_col = RED;}}break;}}_root->_col = BLACK;return true;}void InOrder(){_InOrder(_root);}Node* Find(const K& key){Node* cur = _root;while (cur){if (cur->_kv.first < key){cur = cur->_right;}else if (cur->_kv.first > key){cur = cur->_left;}else{return cur;}}return nullptr;}private:Node* Copy(Node* root){if (root == nullptr)return nullptr;Node* newRoot = new Node(root->_kv);//不一样的地方newRoot->_left = Copy(root->_left);newRoot->_right = Copy(root->_right);return newRoot;}void Destory(Node* root){if (root == nullptr)return;Destory(root->_left);Destory(root->_right);delete root;}void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_kv.first << ":" << root->_kv.second << endl;_InOrder(root->_right);}void RotateL(Node* parent){Node* subr = parent->_right;Node* subrl = subr->_left;parent->_right = subrl;if (subrl)subrl->_parent = parent;Node* parentParent = parent->_parent;subr->_left = parent;parent->_parent = subr;if (parentParent == nullptr){_root = subr;subr->_parent = nullptr;}else{if (parent == parentParent->_left){parentParent->_left = subr;}else{parentParent->_right = subr;}subr->_parent = parentParent;}}void RotateR(Node* parent){Node* subl = parent->_left;//parent的左孩子Node* sublr = subl->_right;//parent左孩子的右孩子parent->_left = sublr;//30的右孩子作为双亲的左孩子if (sublr)//如果30的左孩子的右孩子存在,更新双亲sublr->_parent = parent;Node* parentParent = parent->_parent;// 因为60可能是棵子树,因此在更新其双亲前必须先保存60的双亲subl->_right = parent;//60作为30的右孩子parent->_parent = subl;//更新60的双亲if (parentParent == nullptr)// 如果60是根节点,根新指向根节点的指针{_root = subl;subl->_parent = nullptr;}else // 如果60是子树,可能是其双亲的左子树,也可能是右子树{if (parent == parentParent->_left){parentParent->_left = subl;}else{parentParent->_right = subl;}subl->_parent = parentParent;//更新30的双亲}}Node* _root = nullptr;
};
1.5 红黑树与AVL树的比较
红黑树和AVL树都是高效的平衡二叉树,增删改查的时间复杂度都是O(log_2 N),红黑树不追求绝对平衡,其只需保证最长路径不超过最短路径的2倍,相对而言,降低了插入和旋转的次数,所以在经常进行增删的结构中性能比AVL树更优,而且红黑树实现比较简单,所以实际运用中红黑树更多。