一棵順序統計量樹T經過簡單地在紅黑樹的每一個結點存入附加信息而成。在一個結點x內,除了包含一般的紅黑樹的域key color p left right,還包括域size[x]。這個域中包含以結點x爲根的子樹的結點數(包括x自己),即子樹的大小。若是定義哨兵爲0,也就是設置size[nil]爲0,則有等式 size[x]=size[left[x]]+size[right[x]]+1。數據結構
在出現相等關鍵字的狀況下,定義排序爲按中序遍歷樹時輸出的結點位置,以此消除順序統計樹原定義的不肯定性。spa
檢索具備給定排序的元素:指針
過程OS-SELECT(x,i)返回一個指向以x爲根的子樹中包含第i小關鍵字的結點的指針。code
NODE* osSelect(NODE* x, int i) { int r = x->l->size + 1; if (i == r) { return x; } else if (i < r) { return osSelect(x->l,i); } else { return osSelect(x->r,i-r); } }最壞狀況下,OS-SELECT的總時間與樹的高度成正比。因此對含n個元素的動態集合,運行時間爲O(lgn)。
肯定一個元素的秩:
blog
給定指向一順序統計樹T中結點x的指針,過程OS-RANK返回對T進行中序遍歷後獲得的線性序中x的位置。排序
int osRank(NODE* x) { int r = x->l->size + 1; NODE *y = x; while (y != root) { if (y == y->p->r) { r += y->p->l->size + 1;} y = y->p; } return r; }x的秩能夠視爲在對樹的中序遍歷中,排在x以前的結點個數再加上1。
運行時間與樹的高度成正比:對含n個結點的順序統計樹時間爲O(lgn)。ip
對子樹規模的維護:rem
插入:第一階段沿根降低,將新結點插入爲某個已有結點的孩子。第二階段沿樹上升,作顏色修改和旋轉保持性質。it
第一階段:對路徑上的每一個結點都要增長其size。class
第二階段:對旋轉增長兩行代碼:
y->size = x->size; x->size = x->l->size + x->r->size + 1;刪除:第一階段對查找樹進行操做。第二階段至多三次旋轉。
#define COLOR int #define BLACK 1 #define RED 0 using namespace std; template <class T> class RBTREE{ public: struct NODE{ NODE *p,*l,*r; T key; COLOR c; int size; NODE() {} }NIL; NODE *nil, *root; NODE* newNode(T k, COLOR cl = RED) { NODE *p = new NODE; p->c = cl; p->p = nil; p->l = nil; p->r = nil; p->key = k; p->size = 1; return p; } void deleteNode(NODE *p) { delete p; } void init() { nil = &NIL; nil->c = BLACK; nil->p = nil; nil->l = nil; nil->r = nil; nil->size = 0; root = nil; } RBTREE () { init(); } /*********************************************/ void leftRotate(NODE *x) { NODE *y = x->r; x->r = y->l; if (y->l != nil) { y->l->p = x; } y->p = x->p; if (x->p == nil) { root = y; } else { if (x == x->p->l) { x->p->l = y; } else { x->p->r = y; } } y->l = x; x->p = y; y->size = x->size; x->size = x->l->size + x->r->size + 1; } void rightRotate(NODE *x) { NODE *y = x->l; x->l = y->r; if (y->r != nil) { y->r->p = x; } y->p = x->p; if (x->p == nil) { root = y; } else { if (x == x->p->l) { x->p->l = y; } else { x->p->r = y; } } y->r = x; x->p = y; y->size = x->size; x->size = x->l->size + x->r->size + 1; } /*********************************************/ void rbInsert(NODE *z) { NODE *y = nil; NODE *x = root; while (x != nil) { y = x; y->size += 1; if (z->key < x->key) { x = x->l; } else { x = x->r; } } z->p = y; if (y == nil) { root = z; } else { if (z->key < y->key) { y->l = z; } else { y->r = z; } } z->l = nil; z->r = nil; z->c = RED; rbInsertFixup(z); } void rbInsertFixup(NODE *z) { NODE *y; while (z->p->c == RED) { if (z->p == z->p->p->l) {// z 的父親是爺爺的左兒子 y = z->p->p->r;// z 的叔叔 y if (y->c == RED) {// case 1:叔叔是紅的 z->p->c = BLACK;// 將 z 的父親與叔叔置爲黑 y->c = BLACK; z->p->p->c = RED;// 將 z 的爺爺置爲紅 z = z->p->p;// 問題上移兩層 } else { if (z == z->p->r) {// case 2:z 是右兒子 z = z->p; leftRotate(z);// 左旋,轉爲 case 3 } z->p->c = BLACK;// case 3:z 是左兒子,對z的爺爺作一次右旋便可完成維護 z->p->p->c = RED; rightRotate(z->p->p); } } else if (z->p == z->p->p->r) {// z 的父親是爺爺的右兒子 y = z->p->p->l;// z 的叔叔 y if (y->c == RED) {// case 1:叔叔是紅的 z->p->c = BLACK;// 將 z 的父親與叔叔置爲黑 y->c = BLACK; z->p->p->c = RED;// 將 z 的爺爺置爲紅 z = z->p->p;// 問題上移兩層 } else { if (z == z->p->l) {// case 2:z 是左兒子 z = z->p; rightRotate(z);// 右旋,轉爲 case 3 } z->p->c = BLACK; z->p->p->c = RED; leftRotate(z->p->p); } } } root->c = BLACK; } /*********************************************/ NODE* treeMinimum(NODE *rt) { while (rt->l!=nil) rt=rt->l; return rt; } NODE* treeMaximum(NODE *rt) { while (rt->r!=nil) rt=rt->r; return rt; } NODE* treeSuccessor(NODE *rt) { if (rt->r!=nil) return treeMinimum(rt->r); NODE* pt=rt->p; while (pt!=nil && rt==pt->r) { rt=pt; pt=pt->p; } return pt; } NODE* treePredecessor(NODE *rt) { if (rt->l!=nil) return treeMaximum(rt->l); NODE* pt=rt->p; while (pt!=nil && rt==pt->l) { rt=pt; pt=pt->p; } return pt; } /*********************************************/ NODE* rbDelete(NODE *z) { NODE *y, *x, *t; t = z; while (t != root) { t = t->p; t->size -= 1; } if (z->l == nil || z->r == nil) { y = z; } else { y = treeSuccessor(z); } if (y->l != nil) { x = y->l; } else { x = y->r; } x->p = y->p; if (y->p == nil) { root = x; } else { if (y == y->p->l) { y->p->l = x; } else { y->p->r = x; } } if (y != z) { z->key = y->key; // copy y's satellite data into z } if (y->c == BLACK) { rbDeleteFixup(x); } return y; } void rbDeleteFixup(NODE *x) { NODE *w; while (x != root && x->c == BLACK) { if (x == x->p->l) {// x 爲左兒子 w = x->p->r;// w 是 x 的兄弟 if (w->c == RED) {// case 1:w 爲紅色,必有黑色兒子 w->c = BLACK; x->p->c = RED; leftRotate(x->p); w = x->p->r;// x 的新兄弟必爲黑色 } if (w->l->c == BLACK && w->r->c == BLACK) {// case 2:x 的兄弟 w 是黑色的,w 的兩個兒子都是黑色 w->c = RED;// 去掉一重黑色 x = x->p;// 以 x 父親重複 while 循環 } else { if (w->r->c == BLACK) {// case 3:x 的兄弟 w 是黑色的,w 的左兒子是紅色的,右兒子是黑色 w->l->c = BLACK;// 交換 w 與左兒子的顏色 w->c = RED; rightRotate(w);// w 右旋 w = x->p->r;// 新兄弟是一個有紅色右孩子的黑結點 } w->c = x->p->c;// case 4:x 的兄弟 w 是黑色的,並且 w 的右兒子是紅色的 x->p->c = BLACK; w->r->c = BLACK; leftRotate(x->p); x = root; } } else if (x == x->p->r) {// x 爲右兒子 w = x->p->l;// w 是 x 的兄弟 if (w->c == RED) {// case 1:w 爲紅色,必有黑色兒子 w->c = BLACK; x->p->c = RED; rightRotate(x->p); w = x->p->l;// x 的新兄弟必爲黑色 } if (w->l->c == BLACK && w->r->c == BLACK) {// case 2:x 的兄弟 w 是黑色的,w 的兩個兒子都是黑色 w->c = RED;// 去掉一重黑色 x = x->p;// 以 x 父親重複 while 循環 } else { if (w->l->c == BLACK) {// case 3:x 的兄弟 w 是黑色的,w 的右兒子是紅色的,左兒子是黑色 w->r->c = BLACK;// 交換 w 與右兒子的顏色 w->c = RED; leftRotate(w);// w 左旋 w = x->p->l;// 新兄弟是一個有紅色左孩子的黑結點 } w->c = x->p->c;// case 4:x 的兄弟 w 是黑色的,並且 w 的左兒子是紅色的 x->p->c = BLACK; w->l->c = BLACK; rightRotate(x->p); x = root; } } } x->c = BLACK; } /*********************************************/ NODE* treeSearch(NODE *rt,T k) { if (rt==nil || k==rt->key) return rt; if (k<rt->key) return treeSearch(rt->l,k); else return treeSearch(rt->r,k); } void remove(T key) { NODE *p = treeSearch(root,key); if (p != nil) p = rbDelete(p); deleteNode(p); } /*********************************************/ void insert(T key) { rbInsert(newNode(key)); } void showAll(NODE *p) { if (p != nil) { std::cout << "key = " << p->key << ", color = " << p->c << ", size = " << p->size << std::endl; std::cout << "LEFT:" << std::endl; showAll(p->l); std::cout << "RIGHT:" << std::endl; showAll(p->r); std::cout << "END." << std::endl; } //else { std::cout << " NIL " << endl; } } /********************************************* 數據結構的擴張 *********************************************/ NODE* osSelect(NODE* x, int i) { int r = x->l->size + 1; if (i == r) { return x; } else if (i < r) { return osSelect(x->l,i); } else { return osSelect(x->r,i-r); } } int osRank(NODE* x) { int r = x->l->size + 1; NODE *y = x; while (y != root) { if (y == y->p->r) { r += y->p->l->size + 1;} y = y->p; } return r; } };