演算法導論-13.3-6-紅/黑樹狀結構基於棧實現RB-INSERT

來源:互聯網
上載者:User
題目:

說明如果紅/黑樹狀結構的表示中不提供父指標的話,應該如何有效地實現RB-INSERT

 

思考:

令待插入的元素是z。在插入的過程記錄從根結點到z的路徑,並用棧儲存。那麼z的父結點就是棧頂元素,z的祖父結點就是棧的次頂元素。

在向上迭代的過程同時出棧,控制好出棧的時間,就能正確實現RB-INSERT

 

代碼:
#include <iostream>using namespace std;#define BLACK 0#define RED 1//紅/黑樹狀結構結點結構struct node{node *left;node *right;int key;bool color;node(node *init, int k):left(init),right(init),key(k),color(BLACK){}};//鏈式棧的結點結構struct s_node{node *data;s_node *next;s_node(node *k):data(k),next(NULL){}};//鏈式棧結構struct stack{s_node *top;stack():top(NULL){}}S;//入棧操作void Stack_Insert(stack &S, node *z){s_node *s = new s_node(z);s->next = S.top;S.top = s;}//出棧操作void Stack_Pop(stack &S){s_node *temp = S.top;S.top = S.top->next;delete temp;}//紅/黑樹狀結構結構struct Red_Black_Tree{node *root;//根結點node *nil;//哨兵Red_Black_Tree(){nil = new node(NULL, -1);root = nil;};};//左旋,令y = x->right, 左旋是以x和y之間的鏈為支軸進行旋轉//涉及到的結點包括:x,y,y->left,令node={p,l,r},具體變化如下://x={x->p,x->left,y}變為{y,x->left,y->left}//y={x,y->left,y->right}變為{x->p,x,y->right}//y->left={y,y->left->left,y->left->right}變為{x,y->left->left,y->left->right}void Left_Rotate(Red_Black_Tree *T, node *x){//f指向p[x]node *f = S.top->data;//令y = x->rightnode *y = x->right;//按照上面的方式修改三個結點的指標,注意修改指標的順序x->right = y->left;if(f == T->nil)//特殊情況:x是根結點T->root = y;else if(x == f->left)f->left = y;else f->right = y;y->left = x;}//右旋,令y = x->left, 左旋是以x和y之間的鏈為支軸進行旋轉//旋轉過程與上文類似void Right_Rotate(Red_Black_Tree *T, node *x){//f指向p[x]node *f = S.top->data;node *y = x->left;x->left = y->right;if(f == T->nil)T->root = y;else if(x == f->right)f->right = y;else f->left = y;y->right = x;}//紅/黑樹狀結構調整void RB_Insert_Fixup(Red_Black_Tree *T, node *z){node *y;//唯一需要調整的情況,就是違反性質2的時候,如果不違反性質2,調整結束while(S.top->data->color == RED){//f指向p[z],f2指向p[p[z]]//p[z]是左孩子時,有三種情況node *f = S.top->data;node *f2 = S.top->next->data;if(f == f2->left){//令y是z的叔結點y = f2->right;//第一種情況,z的叔叔y是紅色的if(y->color == RED){//將p[z]和y都著為黑色以解決z和p[z]都是紅色的問題f->color = BLACK;y->color = BLACK;//將p[p[z]]著為紅色以保持性質5f2->color = RED;//把p[p[z]]當作新增的結點z來重複while迴圈Stack_Pop(S);Stack_Pop(S);}//第二種情況:z的叔叔是黑色的,且z是右孩子else{if(z == f->right){//對p[z]左旋,轉為第三種情況//為了保證正確左旋,此時棧元素應該是p[f]Stack_Pop(S);Left_Rotate(T, f);}//第三種情況:z的叔叔是黑色的,且z是左孩子//交換p[z]和p[p[z]]的顏色,並右旋f = f2->left;f->color = BLACK;f2->color = RED;//為了保證正確左旋,此時棧元素應該是p[f2]if(S.top->data == f)Stack_Pop(S);Stack_Pop(S);Right_Rotate(T, f2);}}//p[z]是右孩子時,有三種情況,與上面類似else if(f == f2->right){y = f2->left;if(y->color == RED){f->color = BLACK;y->color = BLACK;f2->color = RED;Stack_Pop(S);Stack_Pop(S);}else{if(z == f->left){Stack_Pop(S);Right_Rotate(T, f);}f = f2->right;f->color = BLACK;f2->color = RED;if(S.top->data == f)Stack_Pop(S);Stack_Pop(S);Left_Rotate(T, f2);}}}T->root->color = BLACK;}//紅/黑樹狀結構的插入void RB_Insert(Red_Black_Tree *T, node *z){//把棧清楚,T->nil是棧頂元素while(S.top->data != T->nil)Stack_Pop(S);node *y = T->nil, *x = T->root;while(x != T->nil){//記錄從root到z的路徑上的點,不包括zStack_Insert(S, x);y = x;if(z->key < x->key)x = x->left;elsex = x->right;}if(y == T->nil)T->root = z;else if(z->key < y->key)y->left = z;elsey->right = z;z->left = T->nil;z->right = T->nil;z->color = RED;RB_Insert_Fixup(T, z);}void Print(node *x){if(x->key == -1)return;Print(x->left);cout<<x->key<<' '<<x->color<<endl;Print(x->right);}void Print(Red_Black_Tree *T){Print(T->root);cout<<endl;}int main(){Red_Black_Tree *T = new Red_Black_Tree;Stack_Insert(S, T->nil);int s[6] = {41, 38, 31, 12, 19, 8}, i;for(i = 0; i< 6; i++){node *z = new node(T->nil, s[i]);RB_Insert(T, z);Print(T);}return 0;}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.