不帶父結點的紅/黑樹狀結構實現

來源:互聯網
上載者:User

標籤:style   class   blog   code   color   使用   

      由於只看到13.3節,所以暫時只實現旋轉插入函數。

思考:如果不帶父結點,那麼在需要訪問z的父結點時,我們可以藉助尋找函數從根結點到待尋找結點z的路徑上必然能找到z的父結點和祖父結點,所以由此可訪問父結點。不過這種方法使得旋轉函數時間增加到O(lgn),而插入函數也相應的增加到O(lgnlgn)。節省了空間上的記憶體,同時增加了已耗用時間。

具體代碼如下:

#include <iostream>using namespace std;#define BLACK 0#define RED 1#define Nil -1#define LEN sizeof(struct Tree)struct Tree{   struct Tree*left;   struct Tree*right;   int key;   int color;};struct Tree*root=NULL;struct Tree*nil=NULL;//非遞迴版本的二叉尋找樹尋找函數struct Tree*ITERATIVE_TREE_SEARCH(struct Tree*x,int k,struct Tree*&p1,struct Tree*&p2){//while (x!=nil&&k!=x->key){p1=x;if (k<x->key){x=x->left;}else x=x->right;if(k!=x->key)//如果沒找到了待尋找值,那麼繼續記錄其祖父和父結點值。{            p2=p1;p1=x;}}return x;}void LEFT_ROTATE(struct Tree*T,struct Tree*x){//左旋轉:分三個步驟①②③來敘述旋轉代碼的。struct Tree*p1=nil,*p2=nil; struct Tree*y=x->right;//設定y結點。x->right=y->left;//本行代碼以及下面的if結構表達的是“y的左孩子成為x的右孩子”。① ITERATIVE_TREE_SEARCH(root,x->key,p1,p2);if(p1==nil)//本行代碼以及下面的if-else結構表達的過程是“y成為該子樹新的根”。②{       root=y;}else if(x==p1->left){       p1->left=y;}else p1->right=y;y->left=x;//本行代碼以及下面一行都表達了“x成為y的左孩子”。③}void RIGHT_ROTATE(struct Tree*T,struct Tree*x){//右旋轉struct Tree*p1=nil,*p2=nil; struct Tree*y=x->left;x->left=y->right; ITERATIVE_TREE_SEARCH(root,x->key,p1,p2);if(p1==nil){root=y;}else if(x==p1->right){p1->right=y;}else p1->left=y;y->right=x;}void RB_INSERT_INSERT_FIXUP(struct Tree*T,struct Tree*z){   struct Tree*p1=nil,*p2=nil;     ITERATIVE_TREE_SEARCH(root,z->key,p1,p2);//p1=z->parent,p2=z->parent->parent   while (1)   {   ITERATIVE_TREE_SEARCH(root,z->key,p1,p2);//p1是父結點 p2是祖父結點   if (p1->color!=RED)   {   break;   }   if (p1==p2->left)   {   struct Tree*y=p2->right;//叔結點   if (y->color==RED)//情況一:叔結點為紅色   {//給p1,y,p2著色以保持性質5。並且解決了z的父結點和z都是紅色結點問題   p1->color=BLACK;   y->color=BLACK;   p2->color=RED;   z=p2;//把z的祖父結點當成新結點z進入下一次迴圈   }    else    {   if (z==p1->right)//情況二:檢查z是否是一個右孩子且叔結點為黑色,前提是p1結點不是葉子結點   {//使用一個左旋讓情況2轉變為情況3   z=p1;   LEFT_ROTATE(T,z);//由於進入if語句後可知旋轉結點不可能是葉子結點,這樣就不用判斷z是否是葉子結點了。   ITERATIVE_TREE_SEARCH(root,z->key,p1,p2);//p1=z->parent,p2=z->parent->parent   }                p1->color=BLACK;//情況三:是z是一個左孩子且叔結點為黑色,改變z的父和祖父結點顏色並做一次右旋,以保持性質5。   p2->color=RED;   if(p2!=nil) RIGHT_ROTATE(T,p2);//由於p2可能是葉子結點,所以最好還是用一個if判斷   }   }    else//下面else分支類似於上面   {   struct Tree*y=p2->left;   if (y->color==RED)   {   p1->color=BLACK;   y->color=BLACK;   p2->color=RED;   z=p2;   }    else    {   if (z==p1->left)   {   z=p1;   RIGHT_ROTATE(T,z);   ITERATIVE_TREE_SEARCH(root,z->key,p1,p2);   }                p1->color=BLACK;   p2->color=RED;   if(p2!=nil) LEFT_ROTATE(T,p2);   }   }   }   root->color=BLACK;//最後給根結點著為黑色。}void RB_INSERT(struct Tree*T,struct Tree*z){struct Tree*y=nil;struct Tree*x=root;while (x!=nil){y=x;if (z->key<x->key){x=x->left;}else x=x->right;}if (y==nil){root=z;} else if(z->key<y->key){y->left=z;}else y->right=z;z->left=nil;z->right=nil;z->color=RED;RB_INSERT_INSERT_FIXUP(T,z);}//中序遍曆void InOderTraverse(struct Tree *p){    if (p!=nil){InOderTraverse(p->left);cout<<p->key<<" "<<p->color<<" "<<endl;InOderTraverse(p->right);}}void main(){nil=new struct Tree[LEN];nil->key=Nil;nil->color=BLACK;root=nil;int i=0;struct Tree*ROOT=new struct Tree[LEN];cin>>ROOT->key;RB_INSERT(nil,ROOT);root=ROOT;    while (i!=12)    {struct Tree*z=new struct Tree[LEN];cin>>z->key;RB_INSERT(root,z);i++;    }InOderTraverse(root);}



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.