一直想寫的一種數據結構,很是厲害的思想,插入,刪除,查找,修改,都是logn的時間複雜度。
比AVL更強大的是,插入刪除綜合效率比AVL要優秀一點。
插入可能須要屢次變色,但旋轉最多3次。刪除可能須要屢次變色,但旋轉最多3次。node
# include <cstdio> # include <iostream> using namespace std; /**************************/ /* 紅黑樹的定義: 1.每一個結點要麼是紅色,要麼是黑色。 2.根結點是黑色的。 3.每一個葉結點(NIL)是黑色的。 4.若是一個結點是紅色的,那麼它的兩個子結點是黑色的。 5.每一個結點到後代的葉結點的簡單路徑上的黑色結點個數相同。 */ // 規定顏色 const int RED = 0; const int BLACK = 1; struct RBTreeNode { int key; int color; // 顏色 RBTreeNode * p; // 父節點 RBTreeNode * left; // 左孩子 RBTreeNode * right; // 右孩子 } * NIL, * root; /// 初始化 void init() { NIL = new RBTreeNode; NIL->color = BLACK; NIL->p = NULL; NIL->left = NULL; NIL->right = NULL; root = NIL; } /// 新建節點 RBTreeNode * create_node(int key) { RBTreeNode * p = new RBTreeNode; p->key = key; p->p = NIL; p->left = NIL; p->right = NIL; p->color = RED; return p; } /// 根據鍵查詢 RBTreeNode * search_node(int key) { RBTreeNode * x = root; while(x!=NIL && x->key != key) { if (key < x->key) x = x->left; else x = x->right; } return x; } /// 查找某子樹最小結點 RBTreeNode * search_minimum(RBTreeNode * p) { if (p == NIL) return NIL; while(p->left != NIL) p = p->left; return p; } /// 查找某子樹最大結點 RBTreeNode * search_maximum(RBTreeNode * p) { if (p == NIL) return NIL; while (p->right != NIL) p = p->right; return p; } /// 查詢結點前驅結點(結點) RBTreeNode * search_predecessor(RBTreeNode * p) { if (p == NIL) return NIL; if (p->left != NIL) { return search_maximum(p->left); // 擁有左子樹,後繼必定是左子樹的最大節點 } else { RBTreeNode * y = p->p; while(y!=NIL && y->left==p) { // 找到高層節點中以p所在的樹爲右子樹的樹的根節點,便是前驅節點 p = y; y = y->p; } return y; } } /// 查找結點後繼節點(結點) RBTreeNode * search_successor(RBTreeNode * p) { if (p == NIL) return NIL; if (p->right != NIL) { return search_minimum(p->right); // 擁有右子樹,後繼必定是右子樹的最小節點 } else { RBTreeNode * y = p->p; while(y!=NIL && y->right==p) { // 找到高層節點中以p所在的樹爲左子樹的樹的根節點,便是後繼節點 p = y; y = y->p; } return y; } } /// 替換子樹, u被v替換 void transplant_node(RBTreeNode * u, RBTreeNode * v) { if (u->p == NIL) { root = v; } else if (u->p->left == u) { u->p->left = v; } else u->p->right = v; if (v != NIL) { v->p = u->p; } } /// 結點左旋(x, y不爲NIL) void left_rotate(RBTreeNode * x) { RBTreeNode * y = x->right; transplant_node(x, y); RBTreeNode * z = y->left; x->p = y; y->left = x; if (z != NIL) z->p = x; x->right = z; } /// 結點右旋(x, y不爲NIL) void right_rotate(RBTreeNode * x) { RBTreeNode * y = x->left; transplant_node(x, y); RBTreeNode * z = y->right; x->p = y; y->right = x; if (z != NIL) z->p = x; x->left = z; } /// 插入結點調整 void insert_node_fixup(RBTreeNode * x) { while (x->p->color == RED) { RBTreeNode * y = x->p; if (y->p->left == y) { // 位於爺結點的左子樹 RBTreeNode * z = y->p->right; if (z->color == RED) { // case1: 叔結點是紅色 z->color = BLACK; y->color = BLACK; y->p->color = RED; x = y->p; continue; } if (y->right == x) { // case2: 叔結點是黑色,是父結點的右孩子 x = x->p; left_rotate(y); } x->p->color = BLACK; // case3: 叔結點是黑色,是父結點的左孩子 x->p->p->color = RED; right_rotate(x->p->p); } else { // 位於爺結點的右子樹 RBTreeNode * z = y->p->left; if (z->color == RED) { z->color = BLACK; y->color = BLACK; y->p->color = RED; x = y->p; continue; } if (y->left == x) { x = x->p; right_rotate(y); } x->p->color = BLACK; x->p->p->color = RED; left_rotate(x->p->p); } } root->color = BLACK; } /// 插入結點(結點) void insert_node(RBTreeNode * z) { RBTreeNode * x = root; RBTreeNode * y = NIL; while (x!=NIL) { y = x; if (z->key < x->key) x = x->left; else x = x->right; } z->p = y; if (y == NIL) root = z; else if (z->key < y->key) y->left = z; else y->right = z; insert_node_fixup(z); } /// 調整刪除結點 void delete_node_fixup(RBTreeNode * x) { while(x != root && x->color == BLACK) { if (x->p->left == x) { RBTreeNode * w = x->p->right; if (w->color == RED) { // case1: 兄弟結點是紅色 x->p->color = RED; w->color = BLACK; left_rotate(x->p); } if (w->left->color == BLACK && w->right->color == BLACK) { // case2: 兄弟結點是黑色,而且雙親爲黑色 w->color = RED; x = x->p; continue; } if (w->right->color != RED) { // case3: 兄弟結點是黑色,左孩子爲紅色 w->left->color = BLACK; w->color = RED; right_rotate(w); } // case4: 兄弟結點是黑色,右孩子是紅色 w->color = x->p->color; w->right->color = BLACK; x->p->color = BLACK; left_rotate(x->p); x = root; } else { RBTreeNode * w = x->p->left; if (w->color == RED) { // case1: 兄弟結點是紅色 x->p->color = RED; w->color = BLACK; right_rotate(x->p); } if (w->right->color == BLACK && w->left->color == BLACK) { // case2: 兄弟結點是黑色,而且雙親爲黑色 w->color = RED; x = x->p; continue; } if (w->left->color != RED) { // case3: 兄弟結點是黑色,左孩子爲紅色 w->right->color = BLACK; w->color = RED; left_rotate(w); } // case4: 兄弟結點是黑色,右孩子是紅色 w->color = x->p->color; w->left->color = BLACK; x->p->color = BLACK; right_rotate(x->p); x = root; } } x->color = BLACK; } /// 刪除結點(結點) void delete_node(RBTreeNode * z) { RBTreeNode * x; // 記錄被刪除的結點在樹中所處的位置 RBTreeNode * y = z; // 記錄實際被刪除的結點 int y_origin_color = y->color; if (z->left == NIL) { x = z->right; transplant_node(z, z->right); } else if (z->right == NIL) { x = z->left; transplant_node(z, z->left); } else { // 左右孩子都存在的狀況 y = search_minimum(z->right); // 找後繼節點 y_origin_color = y->color; x = y->right; if (y != x->right) { // 若是後繼不是右孩子,須要變形。將後繼節點提爲右子樹的根節點 transplant_node(y, y->right); // 後繼節點的左孩子必定不存在,右孩子取代後繼節點 y->right = z->right; y->right->p = y; } // 後繼就是右孩子 transplant_node(z, y); y->left = z->left; // 替換後還須要修改與左子樹的父子關係與顏色 z->left->p = y; y->color = z->color; } delete z; if (y_origin_color == BLACK) delete_node_fixup(x); } /** --- */ bool insert_node(int key) { RBTreeNode * node = search_node(key); if (node != NIL) return false; node = create_node(key); insert_node(node); return true; } bool delete_node(int key) { RBTreeNode * node = search_node(key); if (node == NIL) return false; delete_node(node); return true; } int main() { init(); RBTreeNode * x = NIL; if (x == NIL){ printf("==\n"); } else { printf("!=\n"); } insert_node(1); // insert_node(3); // insert_node(5); // insert_node(7); // insert_node(9); // // insert_node(2); // insert_node(4); // insert_node(6); // insert_node(8); // insert_node(10); // // delete_node(3); // delete_node(7); // delete_node(6); // delete_node(1); while (1) { int k; scanf("%d", &k); RBTreeNode * p = search_node(k); if (p == NIL) printf("NIL\n"); else printf("OK!\n"); } return 0; }