从2-3-4树到红黑树(下) Java与C的实现

欢迎探讨,如有错误敬请指正

如需转载,请注明出处   http://www.cnblogs.com/nullzx/

相关博客:

从2-3-4树到红黑树(上)

从2-3-4树到红黑树(中)

 

1. 实现技巧

为了简化代码和减少不必要的开销,在具体的实现中我们定义一个伪根节点ROOT且只定义一个NIL节点。伪根节点的左子支永远指向NIL节点,NIL节点的左右子支又指向它自身。伪根节点的右子支才表示真正的红黑树。

image

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;
}
posted @ 2016-12-17 19:53 nullzx 阅读(...) 评论(...) 编辑 收藏