首先給出資料結構的擴張的四個步驟:
1)選擇基礎的資料結構;
2)確定要在基礎資料結構中添加哪些資訊;
3)驗證可以用基礎資料結構上的基本修改操作來維護這些新添加的資訊;
4)設計新的操作。
演算法導論書上給出的是紅/黑樹狀結構的一種擴張-動態順序統計。
將容量為n的隨機樣本的各個測定值 (x1,x2,……,xn),從小到大順序的排列,xi所在的順序位置就是它的順序統計量。
動態順序統計是指,在一個動態無序的集合中,任意的順序統計量都可以在O(lgn)時間內確定(線性結構需要O(n)的時間)。
至於擴充紅/黑樹狀結構,最終要的一點就是擴充之後操作已經新域的維護都可以控制在原複雜度內。
擴充步驟如下(c++實現):
1.在紅/黑樹狀結構的成員中添加一個int型的size變更。
class BRTreeNode{private:friend class BRTree;int key;int size;bool color;BRTreeNode* left;BRTreeNode* right;BRTreeNode* parent;}
2.維護資料域,主要有左旋,右旋。
//左旋節點nodebool LeftRotate(BRTreeNode* node){BRTreeNode*y;if(node->right==nil){cout<<"can't left rotate!"<<endl;return 0;}y=node->right;node->right=y->left;if(y->left!=nil){y->left->parent=node;}y->parent=node->parent;if(node->parent==nil){root=y;}else if(node->parent->left==node){node->parent->left=y;}else{node->parent->right=y;}y->left=node;node->parent=y;//維護size域y->size=node->size;node->size=node->left->size+node->right->size+1;return 1;}//右旋節點bool RightRotate(BRTreeNode* node){if(node->left==nil){cout<<"can't rightrotate!"<<endl;return 0;}BRTreeNode* x;x=node->left;node->left=x->right;if(x->right!=nil){x->right->parent=node;}x->parent=node->parent;if(node->parent==nil){root=x;}else if(node->parent->left==node){node->parent->left=x;}else{node->parent->right=x;}node->parent=x;x->right=node;//維護size域node->size=x->size;x->size=x->left->size+x->right->size+1;return 1;}
3.定義新的操作
1)先根遍曆
void Preorder(BRTreeNode*node){if(node!=nil){cout<<node->key<<" "<<"size:"<<node->size<<" ";Preorder(node->left);Preorder(node->right);}}
2)尋找樹中第num小的順序統計量
BRTreeNode* GetIthnode(BRTreeNode*node,int num){int r=node->left->size+1;if(r==num){ cout<<"Got it!"<<node->key<<endl;return node;}else if(r>num){return GetIthnode(node->left,num);}else{return GetIthnode(node->right,num-r);}}
3)確定樹中某個以k為key值的元素的秩
int getRank(BRTreeNode*node,int key){ int r=node->left->size+1; int k=node->key; if(k==key) { return r; } else if(key<k) { return getRank(node->left,key)-1; } else { return r+getRank(node->right,key); }}
最後來測試一下:
int mian(){ BRTree tree; tree.init(); cout<<"Insert 8 numbers:"<<endl; int a[8]={1,2,3,4,5,6,7,8}; int i; for(i=0;i<8;i++) { tree.Insert(a[i]); tree.Preorder(tree.Getroot()); cout<<"Insert finish"<<endl; } cout<<"Get No.6 node"<<endl; tree.GetIthnode(tree.Getroot(),6); cout<<"Get rank of node whick key-value is 6:"<<endl; cout<<tree.getRank(tree.Getroot(),6)<<endl; return 0;}
運行結果:
其餘的操作可以參考之前的一片文章:
演算法導論-紅/黑樹狀結構C++實現
參考:
《演算法導論》第二版