歡迎探討,若有錯誤敬請指正html
如需轉載,請註明出處 http://www.cnblogs.com/nullzx/ java
相關博客:ide
從2-3-4樹到紅黑樹(中)this
爲了簡化代碼和減小沒必要要的開銷,在具體的實現中咱們定義一個僞根節點ROOT且只定義一個NIL節點。僞根節點的左子支永遠指向NIL節點,NIL節點的左右子支又指向它自身。僞根節點的右子支才表示真正的紅黑樹。spa
package datastruct; import java.util.Comparator; public class RBtree<E> { private static class Node<E>{ E e; boolean color; Node<E> left; Node<E> right; Node<E> parent; public Node(E e, boolean color, Node<E> left, Node<E> right, Node<E> parent){ this.e = e; this.color = color; this.left = left; this.right = right; this.parent = parent; } public boolean isRead(){ return color; } } public static final boolean RED = true; public static final boolean BLACK = false; //全部葉子節點的左右子支都指向同一個NIL節點,NIL節點的父節點指向null private final Node<E> NIL; private final Node<E> ROOT;//指向僞根節點的引用 private int size = 0;//節點個數 Comparator<? super E> cmp;//節點大小的比較器 //若是調用了不帶參數的構造函數,則使用該內部類做爲比較器, //但此時泛型E須要繼承Comparable接口,不然運行時會拋出異常 private static class Cmp<T> implements Comparator<T>{ @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public int compare(T e1, T e2) { return ((Comparable)e1).compareTo(e2); } } //不帶比較器的構造函數 public RBtree(){ ROOT = new Node<E>(null, BLACK, null, null, null); NIL = new Node<E>(null, BLACK, null, null, null); NIL.left = NIL; NIL.right = NIL; ROOT.left = NIL; ROOT.right = NIL; ROOT.parent = ROOT; cmp = new Cmp<E>(); } //帶比較器的構造函數 public RBtree(Cmp<? super E> cmp){ if(cmp == null){ throw new IllegalArgumentException(); } this.cmp = cmp; //建立一個僞根節點,該節點的右子支纔是真正的RBtree樹的根,同時該節點還做爲NIL節點 //使用僞根節點節點的目的是,對插入和刪除操做遞歸的形式可以統一 ROOT = new Node<E>(null, BLACK, null, null, null); NIL = new Node<E>(null, BLACK, null, null, null); NIL.left = NIL; NIL.right = NIL; ROOT.left = NIL; ROOT.right = NIL; ROOT.parent = ROOT; } //逆時針旋轉(左旋),參數表示軸節點 private void antiClockwiseRotate(Node<E> X){ Node<E> P = X.parent; Node<E> XR = X.right; if(P.left == X){ P.left = XR; }else{ P.right = XR; } XR.parent = P; X.right = XR.left; if(XR.left != NIL){ XR.left.parent = X; } XR.left = X; X.parent = XR; } //順時針旋轉(右旋),參數表示軸節點 private void clockwiseRotate(Node<E> X){ Node<E> P = X.parent; Node<E> XL = X.left; if(P.left == X){ P.left = XL; }else{ P.right = XL; } XL.parent = P; X.left = XL.right; if(XL.right != NIL){ XL.right.parent = X; } XL.right = X; X.parent = XL; } private Node<E> min(Node<E> X){ while(X.left != NIL){ X = X.left; } return X; } public int size(){ return size; } public boolean contain(E e){ Node<E> X = ROOT.right; while(X != NIL){ int r = cmp.compare(e, X.e); if(r > 0){ X = X.right; }else if(r < 0){ X = X.left; }else{ return true; } } return false; } public boolean insert(E e){ Node<E> P = ROOT; Node<E> X = ROOT.right; int r = 0; while(X != NIL){ r = cmp.compare(e, X.e); P = X; if(r > 0){ X = X.right; }else if(r < 0){ X = X.left; }else{ return false;//元素已存在,插入失敗 } } Node<E> G; Node<E> U; X = new Node<E>(e, RED, NIL, NIL, P);//插入的新節點塗紅 if(r >= 0){//考慮到首次插入的狀況,這個等號是必須的 P.right = X; }else{ P.left = X; } while(true){ P = X.parent; //紅父 if(P.isRead()){ G = P.parent; if(P == G.left){ U = G.right; }else{ U = G.left; } //紅叔 if(U.isRead()){ P.color = BLACK; U.color = BLACK; G.color = RED; X = G;//繼續向上回溯 }else{//黑叔 if(G.left == P){ if(P.left == X){ clockwiseRotate(G); P.color = BLACK; G.color = RED; }else{ antiClockwiseRotate(P); clockwiseRotate(G); X.color = BLACK; G.color = RED; } }else{ if(P.right == X){ antiClockwiseRotate(G); P.color = BLACK; G.color = RED; }else{ clockwiseRotate(P); antiClockwiseRotate(G); X.color = BLACK; G.color = RED; } } break; } }else{//黑父 break; } } size++; ROOT.right.color = BLACK;//有可能向上層進位,根節點圖黑 return true; } public boolean delete(E e){ Node<E> X = ROOT.right; X.color = RED; //刪除時,根先塗紅,1.防止繼續向上回溯 2.只有根節點時也方便刪除 Node<E> P; Node<E> B; while(X != NIL){ int r = cmp.compare(e, X.e); if(r > 0){ X = X.right; }else if(r < 0){ X = X.left; }else{ break; } } if(X == NIL){//沒有找到須要刪除的節點 ROOT.right.color = BLACK; return false; } size--;//必定能夠刪除一個節點 if(X.left != NIL && X.right != NIL){ Node<E> tmp = min(X.right); X.e = tmp.e; X = tmp; } P = X.parent; if(X.right != NIL){ if(X == P.left){ P.left = X.right; }else{ P.right = X.right; } X.right.parent = P; X.color = BLACK; ROOT.right.color = BLACK; return true; }else if(X.left != NIL){ if(X == P.left){ P.left = X.left; }else{ P.right = X.left; } X.left.parent = P; X.color = BLACK; ROOT.right.color = BLACK; return true; }else{ if(X == P.left){ P.left = NIL; }else{ P.right = NIL; } if(X.isRead()){ ROOT.right.color = BLACK; return true; }else{ X = NIL; } } //要刪除的是葉子節點 //四中狀況調整 while(true){ if(X == P.left){ B = P.right; }else{ B = P.left; } if(!B.isRead()){//黑兄 Node<E> BL = B.left;//左侄子 Node<E> BR = B.right;//右侄子 if(B.left.isRead() || B.right.isRead()){//紅侄 if(X == P.left){ if(BR.isRead()){ antiClockwiseRotate(P); BR.color = BLACK; B.color = P.color; P.color = BLACK; }else{ clockwiseRotate(B); antiClockwiseRotate(P); BL.color = P.color; P.color = BLACK; } }else{ if(BL.isRead()){ clockwiseRotate(P); BL.color = BLACK; B.color = P.color; P.color = BLACK; }else{ antiClockwiseRotate(B); clockwiseRotate(P); BR.color = P.color; P.color = BLACK; } } break;//不須要繼續向上回溯 }else{ if(P.isRead()){//黑侄紅父 P.color = BLACK; B.color = RED; break;//不須要繼續向上回溯 }else{//黑侄黑父,繼續向上回溯 B.color = RED; X = P; P = X.parent; } } }else{//紅兄,變換一下紅黑樹的形狀,繼續判斷 if(B == P.right){ antiClockwiseRotate(P); }else{ clockwiseRotate(P); } B.color = BLACK; P.color = RED; //X節點的P節點沒有發生變化,但兄弟節點發生變化 } } ROOT.right.color = BLACK; return true; } public void preorderTraverse(){ preorderTraverse0(ROOT.right); } private void preorderTraverse0(Node<E> X){ if(X != NIL){ System.out.print(X.e + " " + (X.isRead() ? "RED " : "BLACK") + " :"); if(X.left != NIL){ System.out.print(X.left.e + " "); }else{ System.out.print("NIL "); } if(X.right != NIL){ System.out.print(X.right.e + " "); }else{ System.out.print("NIL "); } System.out.println(); preorderTraverse0(X.left); preorderTraverse0(X.right); } } public static void main(String[] args){ RBtree<Integer> rbt = new RBtree<Integer>(); rbt.insert(50); rbt.insert(25); rbt.insert(75); rbt.insert(10); rbt.insert(30); rbt.insert(27); rbt.insert(35); rbt.insert(40); rbt.insert(31); rbt.insert(55); rbt.insert(80); rbt.insert(90); // rbt.insert(22); // rbt.insert(5); // rbt.delete(5); // rbt.delete(51); // rbt.delete(80); // rbt.delete(50); // rbt.delete(75); // rbt.delete(27); // rbt.delete(10); // rbt.delete(25); rbt.delete(10); rbt.preorderTraverse(); System.out.println(); System.out.println("size: " + rbt.size()); System.out.println(rbt.contain(40)); } }
下面的C語言實現是自頂向下的方式實現的,即採用了預合併和預分裂的方法,詳情請見本博客 從2-3-4到紅黑樹(上)。在此方法中咱們將僞根節點的數據定義爲負無窮,這樣插入和刪除操做能夠直接從僞根節點開始。3d
"RBtree.h"中的文件內容htm
#ifndef __RBTREE_H__ #define __RBTREE_H__ typedef enum{Red,Black} colorType; typedef struct Node{ int data; struct Node* left; struct Node* right; colorType color; }Node,*RBtree; int Insert(RBtree* T, int argD); int Delete(RBtree* T, int argD); int Find(RBtree T,int argD); int InOredrTraverse(RBtree T); int PreOredrTraverse(RBtree T); int Destroy(RBtree* T); #endif
RBtree.c中的內容blog
#include "RBtree.h" #include <limits.h> #include <stdlib.h> #include <stdio.h> static int Init(RBtree* T); static int FindMin(Node* ptr,RBtree NullNode); static void RightRotate(RBtree* T); static void LeftRotate(RBtree* T); static void RightPreOrderTra(RBtree ptr,RBtree NullNode); static void RightInOrderTra(RBtree ptr,RBtree NullNode); static void RightPostOrderTra(RBtree ptr,RBtree NullNode); int Insert(RBtree* T, int argD){ Node *X,*P,*GP,*GGP,*NullNode; Node **tmp; if(T == NULL){ return -1; } if(*T == NULL){ if(Init(T) == -1){ return -1; } } GP = NULL; GGP = NULL; P = NULL; X = (*T);//從頭結點開始,防止插入負無窮 NullNode = (*T)->left; NullNode->data = argD; while(X->data != argD){ if(X->left->color == Red && X->right->color == Red){ X->color = Red; X->left->color = Black; X->right->color = Black; if(P->color == Red){ if(argD > GGP->data){ tmp = &(GGP->right); }else{ tmp = &(GGP->left); } if(argD > GP->data){ if(argD > P->data){ LeftRotate(tmp); P->color = Black; GP->color = Red; GP = GGP; //爲可以正確下落一層作保證 }else{ RightRotate(&(GP->right)); LeftRotate(tmp); X->color = Black; GP->color = Red; P = X;//爲可以正確下落一層作保證 GP = P;//爲可以正確下落一層作保證 } }else{ if(argD < P->data){ RightRotate(tmp); P->color = Black; GP->color = Red; GP = GGP; }else{ LeftRotate(&(GP->left)); RightRotate(tmp); X->color = Black; GP->color = Red; P = X; GP = P; } } } } GGP = GP; GP = P; P = X; if(argD > X->data){ X = X->right; } else{ X = X->left; } } if(X != NullNode){ (*T)->right->color = Black; return -1; } X = (Node*)malloc(sizeof(Node)); if(X == NULL){ (*T)->right->color = Black; return -1; } X->color = Red; X->data = argD; X->left = X->right = NullNode; if(argD > P->data){ P->right = X; } else{ P->left = X; } if(P->color == Red){ if(argD > GGP->data){ tmp = &(GGP->right); }else{ tmp = &(GGP->left); } if(argD > GP->data){ if(argD > P->data){ LeftRotate(tmp); P->color = Black; GP->color = Red; GP = GGP; }else{ RightRotate(&(GP->right)); LeftRotate(tmp); X->color = Black; GP->color = Red; P = X; GP = P; } }else{ if(argD < P->data){ RightRotate(tmp); P->color = Black; GP->color = Red; GP = GGP; }else{ LeftRotate(&(GP->left)); RightRotate(tmp); X->color = Black; GP->color = Red; P = X; GP = P; } } } (*T)->right->color = Black; return 0; } int Delete(RBtree* T,int argD){ Node *X,*B,*P,*GP,*NullNode; RBtree *tmp; if(T == NULL || *T == NULL){ return -1; } P = *T; X = (*T)->right;//X從root開始,防止刪除負無窮 NullNode = (*T)->left; B = NullNode; GP = NULL; (*T)->right->color = Red;//根塗紅 while(1){ if(X == NullNode){ (*T)->right->color = Black; return -1;//刪除元素不存在 } if(X->color == Black){ if(X->left->color == Black && X->right->color == Black){ if(B->color == Red){ if(GP->right == P){ tmp = &(GP->right); }else{ tmp = &(GP->left); } B->color = Black; P->color = Red; if(P->right == X){ RightRotate(tmp); B = P->left; GP = *tmp; }else{ LeftRotate(tmp); B = P->right; GP = *tmp; } } if(B->color == Black){ if(B->left->color == Black && B->right->color == Black){ P->color = Black; X->color = Red; B->color = Red; }else{ if(GP->right == P){ tmp = &(GP->right); }else{ tmp = &(GP->left); } if(P->right == X){ if(B->left->color == Red){ P->color = Black; X->color = Red; B->color = Red; B->left->color = Black; RightRotate(tmp); }else if(B->right->color == Red){ P->color = Black; X->color = Red; LeftRotate(&(P->left)); RightRotate(tmp); } }else{ if(B->right->color == Red){ P->color = Black; X->color = Red; B->color = Red; B->right->color = Black; LeftRotate(tmp); }else if(B->left->color == Red){ P->color = Black; X->color = Red; RightRotate(&(P->right)); LeftRotate(tmp); } } } } } } if(X->data == argD){ if(X->left != NullNode && X->right != NullNode){ argD = FindMin(X->right,(*T)->left); X->data = argD; GP = P; P = X; X = P->right; B = P->left; }else if(X->left == NullNode && X->right == NullNode){ if(P->right == X){ P->right = NullNode; } else{ P->left = NullNode; } free(X); if((*T)->left == NullNode && (*T)->right == NullNode){ free(NullNode); free(*T); *T = NULL; return 0; } (*T)->right->color = Black; return 0; }else if(X->left != NullNode){ X->data = X->left->data; free(X->left); X->left = NullNode; (*T)->right->color = Black; return 0; }else if(X->right != NullNode){ X->data = X->right->data; free(X->right); X->right = NullNode; (*T)->right->color = Black; return 0; } }else if(argD > X->data){ GP = P; P = X; X = P->right; B = P->left; }else if(argD < X->data){ GP = P; P = X; X = P->left; B = P->right; } } } int Find(RBtree T,int argD){ if(T != NULL){ Node* root = T->right; Node* NullNode = T->left; while(root != NullNode){ if(root->data == argD){ return 0; }else if(argD > root->data){ root = root->right; }else{ root = root->left; } } } return -1; } int InOredrTraverse(RBtree T){ if(T == NULL){ return -1; } RightInOrderTra(T->right, T->left); return 0; } int PreOredrTraverse(RBtree T){ if(T == NULL){ return -1; } RightPreOrderTra(T->right,T->left); return 0; } int Destroy(RBtree* T){ if(*T == NULL){ return -1; } RightPostOrderTra((*T)->right, (*T)->left); free((*T)->left); free((*T)); *T = NULL; return 0; } static void RightInOrderTra(RBtree ptr,RBtree NullNode){ if(ptr != NullNode){ RightInOrderTra(ptr->left,NullNode); printf("% 3d",ptr->data); RightInOrderTra(ptr->right,NullNode); } } static void RightPreOrderTra(RBtree ptr,RBtree NullNode){ if(ptr != NullNode){ printf("%3d:%c(%3d,%3d)\n", ptr->data,ptr->color == Red? 'R':'B', ptr->left == NullNode?-1:ptr->left->data, ptr->right == NullNode?-1 :ptr->right->data ); RightPreOrderTra(ptr->left,NullNode); RightPreOrderTra(ptr->right,NullNode); } } static void RightPostOrderTra(RBtree ptr,RBtree NullNode){ if(ptr != NullNode){ RightPostOrderTra(ptr->left,NullNode); RightPostOrderTra(ptr->right,NullNode); free(ptr); } } static int Init(RBtree* T){ Node* tmp; tmp = (Node*)malloc(sizeof(Node)); *T = (Node*)malloc(sizeof(Node)); if(*T == NULL || tmp == NULL){ return -1; } (*T)->data = INT_MIN; (*T)->color = Black; (*T)->left = (*T)->right = tmp; tmp->color = Black; tmp->left = tmp->right = tmp; return 0; } static void RightRotate(RBtree* T){ Node* Parent = (*T); Node* LeftSon = (*T)->left; Parent->left = LeftSon->right; LeftSon->right = Parent; *T = LeftSon; } static void LeftRotate(RBtree* T){ Node* Parent = (*T); Node* RightSon = (*T)->right; Parent->right = RightSon->left; RightSon->left = Parent; *T = RightSon; } static int FindMin(Node* ptr,RBtree NullNode){ while(ptr->left != NullNode){ ptr = ptr->left; } return ptr->data; }