歡迎探討,如有錯誤敬請指正
如需轉載,請注明出處 http://www.cnblogs.com/nullzx/
相關博客:
1. 實現技巧
為了簡化代碼和減少不必要的開銷,在具體的實現中我們定義一個偽根節點ROOT且只定義一個NIL節點。偽根節點的左子支永遠指向NIL節點,NIL節點的左右子支又指向它自身。偽根節點的右子支才表示真正的紅黑樹。
2. Java語言實現
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));
}
}
3. C語言實現
下面的C語言實現是自頂向下的方式實現的,即采用了預合並和預分裂的方法,詳情請見本博客 從2-3-4到紅黑樹(上)。在此方法中我們將偽根節點的數據定義為負無窮,這樣插入和刪除操作可以直接從偽根節點開始。
"RBtree.h"中的文件內容
#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中的內容
#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;
}

