算法導論 第十四章:數據結構的擴張

對一種數據結構的擴張過程可分爲四步驟:

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="" />


【注:若有錯誤,請指正~~~】 



發佈了42 篇原創文章 · 獲贊 13 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章