【資料結構】紅黑樹的插入(Insert)
阿新 • • 發佈:2018-12-25
前言:
紅黑樹是一棵二叉搜尋樹,它在每個節點上增加了一個儲存位來表示節點的顏色,可以是Red或Black。通過對任何一條從根到葉子簡單路徑上的顏色來約束,紅黑樹保證最長路徑不超過最短路徑的兩倍,因而近似於平衡。
紅黑樹的基本概念:
紅黑樹是滿足下面紅黑性質的二叉搜尋樹
1. 每個節點,不是紅色就是黑色的
2. 根節點是黑色的
3. 如果一個節點是紅色的,則它的兩個子節點是黑色的(不能有連續的兩個紅節點)
4. 對每個節點,從該節點到其所有後代葉節點的簡單路徑上,均包含相同數目的黑色節點。
5. 每個葉子節點都是黑色的(這裡的葉子節點是指的NIL節點(空節點))
紅黑樹的插入寫法要根據紅黑樹插入的各種情況來分析:
ps:cur為當前節點,p為父節點,g為祖父節點,u為叔叔節點
1.第一種情況
cur為紅,p為紅,g為黑,u存在且為紅
則將p,u改為黑,g改為紅,然後把g當成cur,繼續向上調整。
2.第二種情況
cur為紅,p為紅,g為黑,u不存在/u為黑
p為g的左孩子,cur為p的左孩子,則進行右單旋轉;相反,p為g的右孩子,cur為p的右孩子,則進行左單旋轉
p、g變色--p變黑,g變紅
3.第三種情況
cur為紅,p為紅,g為黑,u不存在/u為黑
p為g的左孩子,cur為p的右孩子,則針對p做左單旋轉;相反,p為g的右孩子,cur為p的左孩子,則針對p做右單旋轉
則轉換成了情況2
上面已經把沒種情況列出來了,其他相反的情況類似,反過來寫一下就行了,具體細節過程見程式碼,
#ifndef __RBTREE_H__ #define __RBTREE_H__ enum colour { RED, BLACK, }; template<class K,class V> struct RBTreeNode { int _col; K _key; V _value; RBTreeNode<K, V>* _left; RBTreeNode<K, V>* _right; RBTreeNode<K, V>* _parent; RBTreeNode(const K& key, const V& value) :_key(key) , _value(value) , _col(RED) , _left(NULL) , _right(NULL) , _parent(NULL) {} }; template<class K,class V> class RBTree { typedef RBTreeNode<K, V> Node; public: RBTree() :_root(NULL) {} 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->_left; } else if (cur->_key < key) { parent = cur; cur = cur->_right; } else return false; } //插入位置 if (parent->_key >key) { cur = new Node(key, value); parent->_left = cur; cur->_parent = parent; } else if (parent->_key < key) { cur = new Node(key, value); parent->_right = cur; cur->_parent = parent; } //插入位置以後,如何調整 while (cur != _root && parent->_col == RED) { Node* grandfather = parent->_parent; Node* uncle = NULL; //左邊的情況 if (parent == grandfather->_left) { //情況一 uncle = grandfather->_right; if (uncle && uncle->_col == RED) { //情況1-> 不需要旋轉 if (cur == parent->_left) { grandfather->_col = RED; parent->_col = BLACK; uncle->_col = BLACK; cur = grandfather; parent = cur->_parent; } //需要旋轉 else if (cur == parent->_right) { RotateL(parent); grandfather->_col = RED; parent->_col = BLACK; uncle->_col = BLACK; cur = grandfather; parent = cur->_parent; } } //情況2,情況3 else if (uncle == NULL || (uncle && uncle->_col == BLACK)) { //情況3 if (cur == parent->_right) { RotateL(parent); } parent->_col = BLACK; grandfather->_col = RED; RotateR(grandfather); break; } } //右邊的情況 else if (parent == grandfather->_right) { //情況1 uncle = grandfather->_left; if (uncle && uncle->_col == RED) { //不需要旋轉 if (cur == parent->_right) { uncle->_col = BLACK; grandfather->_col = RED; parent->_col = BLACK; cur = grandfather; parent = cur->_parent; } //旋轉 else if (cur == parent->_left) { uncle->_col = BLACK; grandfather->_col = RED; parent->_col = BLACK; RotateR(parent); cur = grandfather; parent = cur->_parent; } } else if (uncle == NULL || (uncle && uncle->_col == BLACK)) { //情況2,3 if (cur == parent->_left) { RotateR(parent); } parent->_col = BLACK; grandfather->_col = RED; RotateL(grandfather); break; } } } _root->_col = BLACK; return true; } bool isRBTree() { int blackNodeNum = 0; int curBlackNodeNum = 0; Node* cur = _root; while (cur) { if (cur->_col == BLACK) blackNodeNum++; cur = cur->_left; } return _isRBTree(_root,blackNodeNum,curBlackNodeNum); } void InOrder() { _InOrder(_root); } protected: bool _isRBTree(Node* root,int blackNodeNum,int curBlackNodeNum) { if (root == NULL) return true; if (root->_col == BLACK) curBlackNodeNum++; if (blackNodeNum == curBlackNodeNum) { if (root->_parent == NULL) return true; else if (root->_col == RED && root->_col == root->_parent->_col) { return false; } else { return true; } } return _isRBTree(root->_left, blackNodeNum, curBlackNodeNum) && _isRBTree(root->_right, blackNodeNum, curBlackNodeNum); } void _InOrder(Node* root) { if (root == NULL) return; _InOrder(root->_left); cout << root->_key << " "; _InOrder(root->_right); } 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; parent->_parent = subR; parent = subR; if (parent->_parent == NULL) _root = parent; else if (parent->_parent->_key > parent->_key) { parent->_parent->_left = parent; } else if (parent->_key > parent->_parent->_key) { parent->_parent->_right = parent; } } 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; parent = subL; if (parent->_parent == NULL) _root = parent; else if (parent->_parent->_key > parent->_key) { parent->_parent->_left = parent; } else if (parent->_parent->_key < parent->_key) parent->_parent->_right = parent; } protected: Node* _root; }; void testRBtree() { RBTree<int, int> rbt; int arr[8] = { 2, 5, 12, 16, 18, 26, 3, 1 }; for (int i = 0; i < 8; i++) { rbt.Insert(arr[i], i); } rbt.InOrder(); cout << endl; cout << "isRBTree? ->:" << rbt.isRBTree() << endl; } #endif //__RBTREE_H__