對一種數據結構的擴張過程可分爲四步驟:
1)選擇基礎數據結構
2)確定要在基礎數據結構中添加哪些信息
3)驗證可用基礎數據結構上的基本修改操作來維護這些新添加的信息
4)設計新的操作
動態順序統計
動態順序統計在紅黑樹的基礎上添加x.size域,滿足:x.size = x.left.size+x.right.size+1,擴張的結構如下:
操作:
1)檢索具有給定秩的元素
下面僞代碼返回一個指向以x爲根的子樹中包含第i小關鍵字的節點指針
2)確定元素的秩
僞代碼如下:
3)插入
插入操作會破壞紅黑樹的性質,因此分兩階段進行:
a.對有根至葉子節點的路徑上遍歷的每個節點x都要增加其x.size,新增加的節點的size爲1.(維護size域的額外開銷爲:O(lgn))
b.旋轉調整(次數最多2次)。size域的改變如下:
具體旋轉更新如下:
4)刪除
也分兩階段:
a.從樹中移除欲刪除的點y,更新子樹size (從y上溯到根節點,該路徑上的節點size遞減)。(開銷O(lgn))
b.旋轉調整
完整代碼如下:
#include<iostream>
#include<iomanip>
using namespace std;
#define BLACK 0
#define RED 1
typedef struct OSTNode{
int key;
int size; //addtional information
bool color;
OSTNode *parent;
OSTNode *left;
OSTNode *right;
}OSTNode;
typedef struct OSTree{
OSTNode *root;
}OSTree;
OSTNode NILL={-1,0,BLACK,NULL,NULL,NULL};
OSTNode *NIL=&NILL; //init sentinel NIL
void OST_InorderWalk(OSTNode *x)
{
if(x!=NIL)
{
OST_InorderWalk(x->left);
cout<<setw(3)<<x->key;
if(x->color==1)
cout<<" Red "<<x->size<<endl;
else
cout<<" Black "<<x->size<<endl;
OST_InorderWalk(x->right);
}
}
OSTNode *OST_Search(OSTNode *x,int key)
{
if(x->key == key || x==NIL)
return x;
if(key < x->key)
OST_Search(x->left,key);
else
OST_Search(x->right,key);
}
OSTNode *OST_Minimum(OSTNode *x)
{
while(x->left != NIL)
x=x->left;
return x;
}
void Left_Rotate(OSTree *T,OSTNode *x)
{
OSTNode *y=x->right; //set y
x->right=y->left; //turn y's left subtree into x's right subtree
if(y->left!=NIL)
y->left->parent=x;
y->parent=x->parent; //link x's parent to y;
if(x->parent == NIL)
T->root=y;
else if(x==x->parent->left)
x->parent->left=y;
else
x->parent->right=y;
y->left=x; //put x on y's left
x->parent=y;
y->size=x->size; //Maintaining the inforamtion
x->size=x->left->size+x->right->size+1; //Maintaining the informaiton
}
void Right_Rotate(OSTree *T,OSTNode *x)
{
OSTNode *y=x->left; //set y
x->left=y->right; //link x's left tree into y's right subtree;
if(y->right !=NIL)
y->right->parent=x;
y->parent=x->parent; //link x's parent to y
if(x->parent == NIL)
T->root=y;
else if(x == x->parent->left)
x->parent->left=y;
else
x->parent->right=y;
y->right=x; //put x on y's right
x->parent=y;
y->size=x->size;
x->size=x->left->size+x->right->size+1;
}
void OST_InsertFixup(OSTree *T,OSTNode *z)
{
while(z->parent->color==RED)
{
if(z->parent == z->parent->parent->left)
{
OSTNode *y=z->parent->parent->right;
if(y->color==RED)
{
z->parent->color=BLACK; //case 1
y->color=BLACK; //case 1
z->parent->parent->color=RED; //case 1
z=z->parent->parent; //case 1
}
else
{
if(z==z->parent->right)
{
z=z->parent; //case 2
Left_Rotate(T,z); //case 2
}
z->parent->color=BLACK; //case 3
z->parent->parent->color=RED; //case 3
Right_Rotate(T,z->parent->parent); //case 3
}
}
else
{//a me as then clause with "right" and "left" exchanged
OSTNode *y=z->parent->parent->left;
if(y->color==RED)
{
z->parent->color==BLACK;
y->color=BLACK;
z->parent->parent->color=RED;
z=z->parent->parent;
}
else
{
if(z==z->parent->left)
{
z=z->parent;
Right_Rotate(T,z);
}
z->parent->color=BLACK;
z->parent->parent->color=RED;
Left_Rotate(T,z->parent->parent);
}
}
}
T->root->color=BLACK; //turn the root to BLACK
}
void OST_Insert(OSTree *T,int value)
{
OSTNode *z=new OSTNode();
z->key=value;
z->size=1; //init size
z->color =RED;
z->parent=NIL;
z->left=NIL;
z->right=NIL;
OSTNode *y=NIL; //y is the parent of x
OSTNode *x=T->root;
while(x != NIL)
{
x->size++; //increasing size when inserting
y=x;
if(z->key < x->key)
x=x->left;
else
x=x->right;
}
z->parent=y; //link new node's parent node to y(y's child is NIL)
if(y==NIL)
T->root=z;
else if(z->key < y->key)
y->left=z;
else
y->right =z;
OST_InsertFixup(T,z);
}
/*void OST_Transplant(OSTree *T,OSTNode *u,OSTNode *v)
{
if(u->parent==NIL)
T->root=v;
else if(u==u->parent->left)
u->parent->left=v;
else
u->parent->right=v;
v->parent=u->parent;
}
*/
void OST_DeleteFixup(OSTree *T,OSTNode *x)
{
OSTNode *w;
while(x!=T->root && x->color==BLACK)
{
if(x==x->parent->left)
{
w=x->parent->right; //set w to x's sibling
if(w->color==RED) //case 1:x's sibling w is red
{
w->color=BLACK;
x->parent->color=RED;
Left_Rotate(T,x->parent);
w=x->parent->right;
}
if(w->left->color==BLACK && w->right->color==BLACK)
{ //case 2:x's sibling w is black and both of w's children are black
w->color=RED;
x=x->parent;
}
else
{
if(w->right->color==BLACK)
{//case 3:x's sibling w is black,w's left child is red, and w's right child is black
w->left->color=BLACK;
w->color=RED;
Right_Rotate(T,w);
w=x->parent->right;
}
w->color=x->parent->color; //case 4: x's sibling w is black,and w's right child is red
x->parent->color=BLACK; //.
w->right->color=BLACK; // .
Left_Rotate(T,x->parent); // .
x=T->root; //case 4
}
}
else
{//Same as then clause with "right" and "left" exchanged
w=x->parent->left;
if(w->color==RED)
{
w->color=BLACK;
x->parent->color=RED;
Right_Rotate(T,x->parent);
w=x->parent->left;
}
if(w->left->color==BLACK && w->right->color==BLACK)
{
w->color=RED;
x=x->parent;
}
else
{
if(w->left->color==BLACK)
{
w->right->color=BLACK;
w->color=RED;
Left_Rotate(T,w);
w=x->parent->left;
}
w->color=x->parent->color;
x->parent->color=BLACK;
w->left->color=BLACK;
Right_Rotate(T,x->parent);
x=T->root;
}
}
}
x->color=BLACK;
}
OSTNode *OST_Successor(OSTNode *x){
OSTNode *r = x;
if(r->right != NIL)
return OST_Minimum(r->right);
OSTNode *y = r->parent;
while(y != NIL && r == y->right){
r = y;
y = y->parent;
}
return y;
}
void OST_Delete(OSTree *T,OSTNode *z)
{
OSTNode *x=NULL,*y=NULL,*g=NULL;
if(z->left == NIL || z->right==NIL)
y=z;
else
y=OST_Successor(z);
g=y->parent;
while(g!=NIL) //traverse a simple path from node y up to the root,
{ //decrementing the size attribute of each node on the path
g->size--;
g=g->parent;
}
if(y->left !=NIL)
x=y->left;
else
x=y->right;
x->parent=y->parent;
if(y->parent==NIL)
T->root=x;
else if(y==y->parent->left)
y->parent->left=x;
else
y->parent->right=x;
if(y != z)
z->key=y->key;
if(y->color==BLACK)
OST_DeleteFixup(T,x);
}
/*-----------------------------------------------------------------------*/
OSTNode *OST_Select(OSTNode *x,int i)
{//return the node with ith smallest key in OST
if( x== NIL)
return x;
int r=x->left->size+1;
if( i==r)
return x;
else if(i < r)
return OST_Select(x->left,i);
else
return OST_Select(x->right,i-r);
}
int OST_Rank(OSTree *T,OSTNode *x)
{
int r;
OSTNode *y;
r=x->left->size+1;
y=x;
while(y != T->root)
{
if(y == y->parent->right)
r+=y->parent->left->size+1;
y=y->parent;
}
return r;
}
/*-----------------------------------------------------------------------*/
int main()
{
int A[]={41,38,31,12,19,8,45};
int n=sizeof(A)/sizeof(int);
cout<<"/*---------------Create Order-Statitics Tree-----------------*/"<<endl;
OSTree *T=new OSTree();
T->root=NIL;
for(int i=0;i<n;i++)
OST_Insert(T,A[i]);
cout<<"The Order-Statitics tree is:"<<endl;
OST_InorderWalk(T->root);
cout<<"The root of the OST is:"<<T->root->key<<endl;
cout<<"/*-----------------------------------------------------------*/"<<endl;
cout<<"/*------------Search ith smallest key in OST-----------------*/"<<endl;
int ith_smallest;
cout<<"Please input i:";
cin>>ith_smallest;
OSTNode *ithNode=NIL;
ithNode=OST_Select(T->root,ith_smallest);
if(ithNode==NIL)
cout<<"The OST doesn't exist smallest key."<<endl;
else
{
cout<<"The ith smallest Node is: ";
cout<<"Key:"<<ithNode->key<<" ";
if(ithNode->color==1)
cout<<"Color:Red ";
else
cout<<"Color-Black ";
cout<<"Size:"<<ithNode->size<<endl;
int rank=OST_Rank(T,ithNode);
cout<<"This Node's Rank is:"<<rank<<endl;
}
cout<<"/*----------------------- OST Delete--------------------*/"<<endl;
int dkey;
cout<<"Please input the deleting key:";
cin>>dkey;
OSTNode *dNode=NIL;
dNode=OST_Search(T->root,dkey);
if(dNode==NIL)
cout<<"The deleting key doesn't eixst in the OST."<<endl;
else
{
OST_Delete(T,dNode);
cout<<"After deleting ,the OST is:"<<endl;
OST_InorderWalk(T->root);
cout<<"The root of OST is:"<<T->root->key<<endl;
}
cout<<"/*-----------------------------------------------------------*/"<<endl;
return 0;
}
運行結果:
<img src="https://img-blog.csdn.net/20150716214323469" alt="" />
【注:若有錯誤,請指正~~~】