演算法導論--動態順序統計與區間樹
通過在基礎的資料結構中新增一些附加資訊,來擴張一種標準的資料結構,然後編寫新的操作來支援所需要的應用。下面是介紹在紅黑樹的基礎上擴張的資料結構。
1.動態順序統計
動態順序統計可以在O(lgn)時間內確定任何的順序統計量(即在n個元素的集合中,能在O(lgn)的時間內確定第i小的元素),同時也可以在O(lgn)的時間內計算一個元素的秩(即它在中序遍歷下的位置順序)。
1 新增附加資訊
結點x中加入x.size , size的大小為以x為根的子樹(包含x本身)的內結數,即子樹的大小。我們定義哨兵的size為0,如下圖:
結點內,虛線上方為關鍵字key,下方為結點的size。
可以看出: x.size = x.left.size + x.right.size +1;
enum colors{red,black};//列舉型別
typedef struct Node
{
struct Node * p;
struct Node *left;
struct Node *right;
int key;
enum colors color; //顏色屬性
int size; //新新增的屬性size
}Node;
2 修改基本操作
插入操作:
為了對子樹規模的維護,需要在不影響插入和刪除操作的漸進執行時間的前提下,修改基本的操作。
第一階段:新節點的插入過程中,需要對從根到將要插入的位置過程中遍歷的結點的size加1;
第二階段:維護紅黑樹的左旋和右旋函式需要在最後新增以下語句:
/*左旋*/
y.size = x.size;
x.size = x.left.size + x.right.size +1;
/*右旋*/
x.size = y.size;
y.size = y.left.size + y.right.size +1;
刪除操作:
第一階段:如果要刪除的結點z少於兩個孩子,則從z到根T的過程遍歷的結點size減1;如果要刪除的結點z多於兩個孩子,則從z的後繼y處向上到T的過程中,遍歷的結點size減1;
第二階段:
也是同樣在左右旋過程中,新增以上的語句;
插入操作和刪除操作執行時間都是O(lgn).
3 設計新的操作
1.給定秩的元素的檢索
呼叫函式OS_Select(Node * x,int i)檢索出在以x為根的子樹中,第i小的關鍵字的結點。執行時間為O(lgn);
Node * OS_Select(Node *x,int i)
{
int r =x->left->size+1; //計算以結點x為根的子樹中順序統計量r
if (i == r)
return x;
else if (i < r)
return OS_Select(x->left,i); //在x的左子樹裡繼續遞迴查詢
else
return OS_Select(x->right,i-r);//在x的右子樹裡繼續遞迴查詢
}
2.確定一個元素的秩
給定指向T中,結點x的指標,過程OS_Rank返回對T中序遍歷對應的線性序中x的位置;執行時間為O(lgn)
int OS_Rank(Node *T,Node * x)
{
int r =x->left->size+1; //計算以結點x為根的子樹中順序統計量r
Node * y =x;
while(y != T) //疊加到root根節點位置
{
if (y == y->p->right) //父節點的右子樹輸出在左子樹和根之後,順序統計量疊加
{
r=r+y->p->left->size+1;
}
y = y->p; //若屬於左子樹,直接跳向上層
}
return r;
}
4 完整程式碼
/*
CSDN 勿在浮砂築高臺
http://blog.csdn.net/luoshixian099
演算法導論--順序統計量
2015年5月20日
*/
#include <STDIO.H>
#include <STDLIB.H>
enum colors{red,black};//列舉型別
typedef struct Node
{
struct Node * p;
struct Node *left;
struct Node *right;
int key;
enum colors color;
int size; //新增附加資訊size
}Node;
Node *T_NIL=NULL; //建立全部變數 T_NIL
Node * Tree_Minimum(Node * T) //找最小結點
{
while(T->left != T_NIL)
T=T->left;
return T;
}
void Inorder_Tree_Walk(Node * T) //中序遍歷樹T,輸出
{
if ( T != T_NIL)
{
Inorder_Tree_Walk(T->left); //遞迴其左孩子
printf("%d",T->key); //輸出根的關鍵字
if (T->color == 0)
{
printf("-R");
}
else
{
printf("-B");
}
printf("-(%d) ",T->size);
Inorder_Tree_Walk(T->right); //遞迴其右孩子
}
}
void Pre_Tree_Walk(Node * T) //
{
if ( T != T_NIL)
{
printf("%d ",T->key); //輸出根的關鍵字
Pre_Tree_Walk(T->left); //遞迴其左孩子
Pre_Tree_Walk(T->right); //遞迴其右孩子
}
}
void Left_Rotate(Node **T,Node * x) //左旋
{
Node *y=x->right;
x->right =y->left;
if (y->left != T_NIL)
y->left->p=x;
y->p=x->p;
if(x->p==T_NIL)
*T=y;
else if (x == x->p->left)
x->p->left = y;
else
x->p->right = y;
y->left = x;
x->p=y;
y->size = x->size; //新增語句維護size
x->size = x->left->size+x->right->size+1;
}
void Right_Rotate(Node **T,Node * y) //右旋
{
Node *x=y->left;
y->left =x->right;
if (x->right != T_NIL)
x->right->p=y;
x->p=y->p;
if(y->p==T_NIL)
*T=x;
else if (y == y->p->left)
y->p->left = x;
else
y->p->right = x;
x->right = y;
y->p=x;
x->size = y->size; //新增語句維護size
y->size = y->left->size+y->right->size+1;
}
Node* RB_Insert_Fixup(Node *T,Node *z)
{
Node * y=NULL;
while( z->p->color == red) //違反了性質4,迭代進行修正
{
if (z->p == z->p->p->left)
{
y = z->p->p->right;
if ( y->color == red) // case 1 叔結點為紅色
{
z->p->color = black; //父節點塗黑
y->color = black; //叔結點塗黑
z->p->p->color = red; //祖結點塗紅
z = z->p->p; //向上迭代,更新z的位置
}
else if ( z == z->p->right) //case 2 叔結點為黑色且z為雙親的右孩子
{
z = z->p;
Left_Rotate(&T,z);
z->p->color = black; //case2 已轉為 case3 繼續處理
z->p->p->color = red;
Right_Rotate(&T,z->p->p);// while迴圈終止
}
else // case 3 叔結點為黑色且z為雙親的左孩子
{
z->p->color = black;
z->p->p->color = red;
Right_Rotate(&T,z->p->p);// while迴圈終止
}
}
else //對稱處理
{
y = z->p->p->left;
if ( y->color == red) // case 1 叔結點為紅色
{
z->p->color = black;
y->color = black;
z->p->p->color = red;
z = z->p->p;
}
else if ( z == z->p->left) //case 2 叔結點為黑色且z為雙親的右孩子
{
z = z->p;
Right_Rotate(&T,z);
z->p->color = black;
z->p->p->color = red;
Left_Rotate(&T,z->p->p);//
}
else // case 3
{
z->p->color = black;
z->p->p->color = red;
Left_Rotate(&T,z->p->p);
}
}
}
T->color = black; //保證不會違反性質2,對根節點塗黑
return T;
}
Node *RB_Insert(Node *Root,Node * z) //紅黑樹插入,返回樹的根
{
Node * y=T_NIL;
Node * x=Root;
while( x != T_NIL) //找到結點z要插入的位置
{
x->size+=1; //插入過程中,遍歷的結點size加1
y=x;
if (z->key < x->key)
x = x->left;
else
x = x->right;
}
z->p = y;
if ( y == T_NIL) //插入第一個結點作為根節點的情況
Root = z;
else if (z->key < y->key)
y->left = z;
else
y->right = z;
Root = RB_Insert_Fixup(Root,z); //插入完畢後,對紅黑樹的顏色進行修正
return Root;
}
Node * Establish(int *A,int len) //建立紅黑樹
{
Node * T,*node;
int i=0;
node=NULL;
T_NIL=(Node *)malloc(sizeof(Node)); //建立T_NIL結點
T_NIL->p=NULL;
T_NIL->left=NULL;
T_NIL->right=NULL;
T_NIL->key=-1;
T_NIL->color=black;
T_NIL->size=0;
T=T_NIL;
for (i=0;i<len;i++)
{
node =(Node *)malloc(sizeof(Node));
node->p =T_NIL;
node->left=T_NIL;
node->right=T_NIL;
node->key=A[i];
node->color=red;
node->size=1;
T=RB_Insert(T,node);
}
return T;
}
void RB_Transplant(Node **T,Node * u,Node * v) //結點替代函式
{
if (u->p == T_NIL)
*T = v;
else if (u == u->p->left)
u->p->left = v;
else
u->p->right = v;
v->p = u->p; //此處賦值無條件,v如果是T_NIL也要進行賦值
}
void RB_Delete_Fixup(Node * T,Node * x)
{
Node *w=NULL;
while( x != T && x->color == black) //迴圈迭代處理
{
if ( x == x->p->left )
{
w = x->p->right;
if (w->color == red) // case 1 ------> case 2 , case 3 ,case 4
{
w->color = black;
x->p->color =red;
Left_Rotate(&T,x->p);
w = x->p->right;
}
if ( w->left->color == black && w->right->color == black ) //case 2 ------>go on / stop
{
w->color = red;
x = x->p;
}
else if ( w->right->color == black) // case 3 ---->case 4---->stop
{
w->left->color = black;
w->color =red ;
Right_Rotate(&T,w);
w = x->p->right ; //轉成case 4處理
w->color = x->p->color;
x->p->color = black;
w->right->color = black;
Left_Rotate(&T,x->p);
x = T;
}
else // case 4 ------------------->stop
{
w->color = x->p->color;
x->p->color = black;
w->right->color = black;
Left_Rotate(&T,x->p);
x = T;
}
}
else
{
w = x->p->left;
if (w->color == red) // case 1 ------> case 2 , case 3 ,case 4
{
w->color = black;
x->p->color =red;
Right_Rotate(&T,x->p);
w = x->p->left;
}
if ( w->right->color == black && w->left->color == black ) //case 2 ------>go on/stop
{
w->color = red;
x = x->p;
}
else if ( w->left->color == black) // case 3 -----> case 4----->stop
{
w->right->color = black;
w->color =red ;
Left_Rotate(&T,w);
w = x->p->left ; //轉成case 4處理
w->color = x->p->color;
x->p->color = black;
w->left->color = black;
Right_Rotate(&T,x->p);
x = T;
}
else // case 4 -------------->stop
{
w->color = x->p->color;
x->p->color = black;
w->left->color = black;
Right_Rotate(&T,x->p);
x = T;
}
}
}
x->color = black; //可能由case2退出,那把x塗黑即可,見分析!也可能有case4退出,把根節點塗黑
}
Node * RB_Delete(Node *T ,Node *z)
{
Node * x =NULL;
Node * y =z;
Node *temp=y->p;
enum colors y_original_color = y->color; //記錄下刪除前z的顏色
if ( z->left == T_NIL) //左子樹不存在的情況
{
x = z->right;
RB_Transplant(&T,z,z->right);
}
else if ( z->right == T_NIL) //右子樹不存在
{
x = z->left;
RB_Transplant(&T,z,z->left);
}
else //左右都存在的情況
{
y = Tree_Minimum(z->right); //找到後繼y
temp=y->p;
y_original_color = y->color; //記錄下y轉移前的顏色
x = y->right;
if ( y->p == z) //如果y是z的子結點
{
x->p = y;
}
else
{
RB_Transplant(&T,y,y->right); //如果y不是z的子結點,用y的右子樹代替y的位置
y->right = z->right;
y->right->p = y;
}
RB_Transplant(&T,z,y); //y替代z的位置 ,不論y是不是T_NIL
y->left = z->left;
y->left->p = y;
y->color = z->color; //把y的顏色改成z的顏色
y->size =y->left->size+y->right->size+1;
}
while(temp != T_NIL) //從刪除的位置或後繼的位置向上遍歷size--,直到根節點為止
{
temp->size--;
temp = temp->p;
}
if ( y_original_color == black) //判斷y的顏色,若為黑色,需要修復
RB_Delete_Fixup(T,x);
return T;
}
Node * Tree_Search(Node *T ,int k) //尋找數k是否在樹中,且返回數k的地址
{
while(T !=T_NIL && T->key != k)
{
if ( k < T->key)
T=T->left;
else
T=T->right;
}
if ( T == T_NIL)
{
return NULL;
}
else
{
return T;
}
}
Node * OS_Select(Node *x,int i) //確定以x為根節點的子樹,第i小的關鍵字
{
int r =x->left->size+1;
if (i == r)
return x;
else if (i < r)
return OS_Select(x->left,i);
else
return OS_Select(x->right,i-r);
}
int OS_Rank(Node *T,Node * x) //確定x在樹T中序遍歷中的位置順序
{
int r =x->left->size+1;
Node * y =x;
while(y != T)
{
if (y == y->p->right)
{
r=r+y->p->left->size+1;
}
y = y->p;
}
return r;
}
void main()
{
int A[]={2,5,1,6,3,8,4,9,7};
int length = sizeof(A)/sizeof(A[0]); //陣列A的長度
Node *T =Establish(A,length); //建立紅黑樹,返回根節點T
printf("中序遍歷:\n");
Inorder_Tree_Walk(T);printf("\n"); //中序遍歷輸出
printf("先序遍歷:\n"); //先序遍歷輸出
Pre_Tree_Walk(T);printf("\n");
printf("__%d__\n",OS_Select(T,5)->key);
printf("--%d--\n",OS_Rank(T,Tree_Search(T,3)));
printf("-----------刪除操作後-------------\n");
T=RB_Delete(T,Tree_Search(T,2));
T=RB_Delete(T,Tree_Search(T,5));
T=RB_Delete(T,Tree_Search(T,7));
T=RB_Delete(T,Tree_Search(T,4));
printf("中序遍歷:\n");
Inorder_Tree_Walk(T);
printf("\n");
printf("先序遍歷:\n");
Pre_Tree_Walk(T);
printf("\n");
}
2.區間樹
區間樹是通過擴張紅黑樹來構成由區間構成的動態集合。結點的屬性由一個關鍵字key變成了一個區間。
1.新增附加資訊
新增區間資訊INT,INT結構包含區間的左右端點。還包含Max屬性,它是以自身為根的子樹中所有的區間的端點最大值。(上圖中虛線下方)
enum colors{red,black};//列舉型別
struct Interval //區間
{
int low;
int high;
};
typedef struct Node
{
struct Node * p;
struct Node *left;
struct Node *right;
enum colors color;
//新增的屬性
struct Interval INT; //儲存結點區間資訊
int Max; //以結點為根的所有區間端點的最大值
}Node;
2.修改基本操作
修改紅黑樹的插入和刪除操作維新增的資訊,都能保證在O(lgn)的時間內完成;
1.插入操作:
第一步:由於區間樹採用區間左端點作為關鍵字進行插入,遍歷時通過比較INT.low的方式插入;插入前令Max=high,插入時從根節點開始遍歷到要插入的位置,把遍歷的結點的Max與新新增的結點z的Max進行比較,如果z.Max>x.Max ,更新結點的x.Max=z.Max
Node *Interval_Insert(Node *Root,Node * z) //紅黑樹插入,返回樹的根
{
Node * y=T_NIL;
Node * x=Root;
while( x != T_NIL) //找到結點z要插入的位置
{
if ( z->Max > x->Max) //比較新插入的結點z與結點x的Max大小;
{
x->Max = z->Max;
}
y=x;
if (z->INT.low < x->INT.low)
x = x->left;
else
x = x->right;
}
z->p = y;
if ( y == T_NIL) //插入第一個結點作為根節點的情況
Root = z;
else if (z->INT.low < y->INT.low)
y->left = z;
else
y->right = z;
Root = Interval_Insert_Fixup(Root,z); //插入完畢後,對紅黑樹的顏色進行修正
return Root;
}
第二步:由於左旋右旋會破壞區間的性質,在函式程式碼後新增更新資訊
void Left_Rotate(Node **T,Node * x) //左旋
{
Node *y=x->right;
x->right =y->left;
if (y->left != T_NIL)
y->left->p=x;
y->p=x->p;
if(x->p==T_NIL)
*T=y;
else if (x == x->p->left)
x->p->left = y;
else
x->p->right = y;
y->left = x;
x->p=y;
y->Max = x->Max; //新增語句維護Max
x->Max = GetMax(x->left->Max,x->right->Max,x->INT.high);
}
void Right_Rotate(Node **T,Node * y) //右旋
{
Node *x=y->left;
y->left =x->right;
if (x->right != T_NIL)
x->right->p=y;
x->p=y->p;
if(y->p==T_NIL)
*T=x;
else if (y == y->p->left)
y->p->left = x;
else
y->p->right = x;
x->right = y;
y->p=x;
x->Max = y->Max; //新增語句維護Max
y->Max = GetMax(y->left->Max,y->right->Max,y->INT.high);
}
2.刪除操作
第一步:被刪除的結點z可能會影響整個區間樹的性質,如果結點z少於兩個孩子,則沿著z上升到根節點為止,對樹重新更新維護;如果有兩個孩子則從後繼出發,進行維護;
while( temp != T_NIL ) //從要刪除的結點或其後繼開始向上修復區間樹
{
temp->Max = GetMax(temp->left->Max,temp->right->Max,temp->INT.high);
temp = temp->p; //每次一層,至多lgn層
}
第二步:同上,也是在左旋右旋函式後新增程式碼。
3.設計新的操作
判斷給定的一個區間i位於區間樹的哪個位置。區間之間的關係:
a重疊的情況;b、c不重疊的情況
不重疊的情況用程式碼表示為
x->INT.high < i->low
x->INT.low > i->high
如果存在區間與i重疊則返回結點的位置,否則返回T_NIL
Node * Interval_Search(Node *T ,struct Interval *i) //尋找數k是否在樹中,且返回數k的地址
{
Node * x = T;
while(x != T_NIL && ((x->INT.high < i->low)||(x->INT.low > i->high))) //不重疊
{
if (x->left != T_NIL && x->left->Max >= i->low) //在其左子樹中搜索
{
x = x->left;
}
else
{
x = x->right;
}
}
return x;
}
每次迭代都是一層,至多lgn層;所以耗時O(lgn)的時間
4.完整程式碼
/*
CSDN 勿在浮砂築高臺
http://blog.csdn.net/luoshixian099
演算法導論--區間樹
2015年5月20日
*/
#include <STDIO.H>
#include <STDLIB.H>
enum colors{red,black};//列舉型別
struct Interval //區間
{
int low;
int high;
};
typedef struct Node
{
struct Node * p;
struct Node *left;
struct Node *right;
enum colors color;
//新增的屬性
struct Interval INT; //儲存結點區間資訊
int Max; //以結點為根的所有區間端點的最大值
}Node;
Node *T_NIL=NULL; //建立全部變數 T_NIL
int GetMax(int a,int b,int c) //返回a,b,c最大值
{
return a>b?(a>c?a:c):(b>c?b:c);
}
Node * Tree_Minimum(Node * T) //找最小結點
{
while(T->left != T_NIL)
T=T->left;
return T;
}
void Inorder_Tree_Walk(Node * T) //中序遍歷樹T,輸出
{
if ( T != T_NIL)
{
Inorder_Tree_Walk(T->left); //遞迴其左孩子
printf("%d",T->INT.low); //輸出根的關鍵字
if (T->color == 0)
{
printf("-R(%d) ",T->Max);
}
else
{
printf("-B(%d) ",T->Max);
}
Inorder_Tree_Walk(T->right); //遞迴其右孩子
}
}
void Pre_Tree_Walk(Node * T) //
{
if ( T != T_NIL)
{
printf("%d ",T->INT.low); //輸出根的關鍵字
Pre_Tree_Walk(T->left); //遞迴其左孩子
Pre_Tree_Walk(T->right); //遞迴其右孩子
}
}
void Left_Rotate(Node **T,Node * x) //左旋
{
Node *y=x->right;
x->right =y->left;
if (y->left != T_NIL)
y->left->p=x;
y->p=x->p;
if(x->p==T_NIL)
*T=y;
else if (x == x->p->left)
x->p->left = y;
else
x->p->right = y;
y->left = x;
x->p=y;
y->Max = x->Max; //新增語句維護Max
x->Max = GetMax(x->left->Max,x->right->Max,x->INT.high);
}
void Right_Rotate(Node **T,Node * y) //右旋
{
Node *x=y->left;
y->left =x->right;
if (x->right != T_NIL)
x->right->p=y;
x->p=y->p;
if(y->p==T_NIL)
*T=x;
else if (y == y->p->left)
y->p->left = x;
else
y->p->right = x;
x->right = y;
y->p=x;
x->Max = y->Max; //新增語句維護Max
y->Max = GetMax(y->left->Max,y->right->Max,y->INT.high);
}
Node* Interval_Insert_Fixup(Node *T,Node *z)
{
Node * y=NULL;
while( z->p->color == red) //違反了性質4,迭代進行修正
{
if (z->p == z->p->p->left)
{
y = z->p->p->right;
if ( y->color == red) // case 1 叔結點為紅色
{
z->p->color = black; //父節點塗黑
y->color = black; //叔結點塗黑
z->p->p->color = red; //祖結點塗紅
z = z->p->p; //向上迭代,更新z的位置
}
else if ( z == z->p->right) //case 2 叔結點為黑色且z為雙親的右孩子
{
z = z->p;
Left_Rotate(&T,z);
z->p->color = black; //case2 已轉為 case3 繼續處理
z->p->p->color = red;
Right_Rotate(&T,z->p->p);// while迴圈終止
}
else // case 3 叔結點為黑色且z為雙親的左孩子
{
z->p->color = black;
z->p->p->color = red;
Right_Rotate(&T,z->p->p);// while迴圈終止
}
}
else //對稱處理
{
y = z->p->p->left;
if ( y->color == red) // case 1 叔結點為紅色
{
z->p->color = black;
y->color = black;
z->p->p->color = red;
z = z->p->p;
}
else if ( z == z->p->left) //case 2 叔結點為黑色且z為雙親的右孩子
{
z = z->p;
Right_Rotate(&T,z);
z->p->color = black;
z->p->p->color = red;
Left_Rotate(&T,z->p->p);//
}
else // case 3
{
z->p->color = black;
z->p->p->color = red;
Left_Rotate(&T,z->p->p);
}
}
}
T->color = black; //保證不會違反性質2,對根節點塗黑
return T;
}
Node *Interval_Insert(Node *Root,Node * z) //紅黑樹插入,返回樹的根
{
Node * y=T_NIL;
Node * x=Root;
while( x != T_NIL) //找到結點z要插入的位置
{
if ( z->Max > x->Max) //比較新插入的結點z與結點x的Max大小;
{
x->Max = z->Max;
}
y=x;
if (z->INT.low < x->INT.low)
x = x->left;
else
x = x->right;
}
z->p = y;
if ( y == T_NIL) //插入第一個結點作為根節點的情況
Root = z;
else if (z->INT.low < y->INT.low)
y->left = z;
else
y->right = z;
Root = Interval_Insert_Fixup(Root,z); //插入完畢後,對紅黑樹的顏色進行修正
return Root;
}
Node * Establish(int A[][2],int len) //建立紅黑樹
{
Node * T,*node;
int i=0;
node=NULL;
T_NIL=(Node *)malloc(sizeof(Node)); //建立T_NIL結點
T_NIL->p=NULL;
T_NIL->left=NULL;
T_NIL->right=NULL;
T_NIL->INT.low=-1;
T_NIL->color=black;
T_NIL->Max=0;
T=T_NIL;
for (i=0;i<len;i++)
{
node =(Node *)malloc(sizeof(Node));
node->p =T_NIL;
node->left=T_NIL;
node->right=T_NIL;
node->INT.low=A[i][0]; //以INT.low左作為關鍵字
node->INT.high=A[i][1];
node->Max = A[i][1];
node->color=red;
T=Interval_Insert(T,node);
}
return T;
}
void RB_Transplant(Node **T,Node * u,Node * v) //結點替代函式
{
if (u->p == T_NIL)
*T = v;
else if (u == u->p->left)
u->p->left = v;
else
u->p->right = v;
v->p = u->p; //此處賦值無條件,v如果是T_NIL也要進行賦值
}
Node* Interval_Delete_Fixup(Node * T,Node * x)
{
Node *w=NULL;
while( x != T && x->color == black) //迴圈迭代處理
{
if ( x == x->p->left )
{
w = x->p->right;
if (w->color == red) // case 1 ------> case 2 , case 3 ,case 4
{
w->color = black;
x->p->color =red;
Left_Rotate(&T,x->p);
w = x->p->right;
}
if ( w->left->color == black && w->right->color == black ) //case 2 ------>go on / stop
{
w->color = red;
x = x->p;
}
else if ( w->right->color == black) // case 3 ---->case 4---->stop
{
w->left->color = black;
w->color =red ;
Right_Rotate(&T,w);
w = x->p->right ; //轉成case 4處理
w->color = x->p->color;
x->p->color = black;
w->right->color = black;
Left_Rotate(&T,x->p);
x = T;
}
else // case 4 ------------------->stop
{
w->color = x->p->color;
x->p->color = black;
w->right->color = black;
Left_Rotate(&T,x->p);
x = T;
}
}
else
{
w = x->p->left;
if (w->color == red) // case 1 ------> case 2 , case 3 ,case 4
{
w->color = black;
x->p->color =red;
Right_Rotate(&T,x->p);
w = x->p->left;
}
if ( w->right->color == black &&a