红黑树的C实现

看了nginx的源码,其中的定时器采用的数据结构是红黑树,而linux内核中高级数据结构也采用了红黑树,由此可见红黑树效率确实很高。

红黑树是一种局部平衡树,不像AV树那样绝对平衡。但是实现起来也比较复杂,鄙人水平有限,在了解了红黑树原理之后自己用C实现了

红黑树,花了一天时间调试才通过,建议大家也写写,有得地方注释不够清楚,下次补充。


一般的,红黑树,满足以下性质,即只有满足以下全部性质的树,我们才称之为红黑树:
 1)每个结点要么是红的,要么是黑的。
 2)根结点是黑的。
 3)每个叶结点,即空结点(NIL)是黑的。
 4)如果一个结点是红的,那么它的俩个儿子都是黑的。
 5)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define RED 1
#define BLOCK 0

//瀹氫箟鑺傜偣
typedef struct myrbtree
{
	int key;   //鑺傜偣鍏抽敭瀛楋紝鐢ㄤ互鍞竴鏍囪瘑涓€涓妭鐐�
	struct myrbtree *parent,*left,*right;
	int color;  //绾㈤粦灞炴€�
}Rbnode,*Rbpoint;

Rbpoint sentinel ;  //鍝ㄥ叺锛屾墍鏈夌殑鍙跺瓙鑺傜偣鎸囧悜鍝ㄥ叺

Rbpoint createnode(int key)  //鍒涘缓涓€涓┖鑺傜偣
{
	Rbpoint new = (Rbpoint)malloc(sizeof(Rbnode));
	new->key = key;
	new->parent = sentinel;
	new->left = sentinel;
	new->right = sentinel;
	new->color = RED;
	return new;	
}

//涓牴閬嶅巻浜屽樊鏍戝嚱鏁�
static void firstroot(Rbpoint root)
{
	Rbpoint tmp = root;
	if(tmp->left != sentinel)
	{
		firstroot(tmp->left);
	}
	printf("%d,",tmp->key);
	if(tmp->right != sentinel)
	{
		firstroot(tmp->right);
	
	}
}

//鍒涘缓鏍硅妭鐐瑰嚱鏁�

Rbpoint createroot(int key)
{
	Rbpoint root = createnode(key);
	root->color = BLOCK; //鏍硅妭鐐瑰畾涔変负榛戣壊
}

Rbpoint rbbalance(Rbpoint ,Rbpoint );  
Rbpoint leftrobate(Rbpoint ,Rbpoint);
Rbpoint rightrobate(Rbpoint ,Rbpoint);


Rbpoint rbinsert(Rbpoint root,Rbpoint new)  //鎻掑叆涓€涓妭鐐癸紝root涓烘牴,new涓烘柊鎻掑叆鑺傜偣
{
	if(root->color != BLOCK)
	{
		printf("root not BLOCK\n");
		exit(0);
	}
	if(root == sentinel)
		return new;
	Rbpoint tmp = root;
	while(tmp != sentinel) //绾㈤粦鏍戞槸鎺掑簭鏍戯紝鏂拌妭鐐规彃鍏ュ埌鏍戜腑骞舵帓搴�
	{
		if(new->key > tmp->key)
		{
			if(tmp->right == sentinel) //澶т簬褰撳墠鑺傜偣锛屽垯寰€鍙虫煡鎵剧┖浣嶆彃鍏�
			{
				tmp->right = new;
				new->parent = tmp;
				break;
			}
			else
				tmp = tmp->right;
			
		}
		else     //灏忎簬褰撳墠鑺傜偣锛屽線宸︽煡鎵剧┖浣嶆彃鍏�
		{
			if(tmp->left == sentinel)
			{
				tmp->left = new;
				new->parent = tmp;
				break;
			}
			else
				tmp = tmp->left;
		
		}
	}
	
	root = rbbalance(root,new);  //鎻掑叆涔嬪悗闇€瑕佸钩琛★紝閫氳繃绉诲姩锛岀炕杞互婊¤冻绾㈤粦鏍戞潯浠�
	return root;
}


Rbpoint leftrobate(Rbpoint root,Rbpoint new)  //宸︾炕杞�
{
	Rbpoint tmp;
	if(new == root)
		return root;
	tmp = new->parent;
	if(tmp->parent != sentinel) //缈昏浆鐨勬牴涓烘牴鑺傜偣
	{
		if(tmp->parent->left == tmp)
			tmp->parent->left = new;
		else
			tmp->parent->right = new;
		new->parent = tmp->parent;
		tmp->right = new->left;
		new->left->parent = tmp;
		tmp->parent = new;
		new->color = BLOCK;
		tmp->color = RED;
		new->left = tmp;
		return root;
	}
	else          //缈昏浆鐨勬牴涓嶄负鏍硅妭鐐�
	{
		new->parent = sentinel;
		tmp->right = new->left;
		new->left->parent = tmp;
		tmp->parent = new;
		new->color = BLOCK;
		tmp->color = RED;
		new->left = tmp;
		return new;
	}
}

Rbpoint rightrobate(Rbpoint root,Rbpoint new)  //鍙堢炕杞紝缈昏浆杩囩▼涓庡乏缈昏浆绫讳技
{
	Rbpoint tmp;
	tmp = new->parent;
	if(tmp->parent != sentinel)
	{
		if(tmp->parent->right == tmp)
		tmp->parent->right = new;
		else
		tmp->parent->left = new;

		new->parent = tmp->parent;
		tmp->left = new->right;
		new->right->parent = tmp;
		tmp->parent = new;
		new->color = BLOCK;
		tmp->color = RED;
		new->right = tmp;
		return root;
	}
	else
	{
		new->parent = sentinel;
		tmp->left = new->right;
		new->right->parent = tmp;
		new->color = BLOCK;
		tmp->color = RED;
		new->right = tmp;
		tmp->parent = new;
		return new;
	}
}

Rbpoint rbbalance(Rbpoint root,Rbpoint new)  //瀵逛簩鎿︽爲杩涜骞宠 鍖�
{
	Rbpoint tmp;
	if(new == root)
		return root;
	if(new->parent->color == BLOCK)
		return root;
	if((new->parent->parent->left != sentinel)&&(new->parent->parent->right != sentinel)&&(new->parent->parent->left->color == RED)&&(new->parent->parent->right->color == RED))
	{
		new->parent->parent->left->color = BLOCK;
		new->parent->parent->right->color = BLOCK;
		if(new->parent->parent == root)
		{
			root->color = BLOCK;
			return  root;
		}
		new->parent->parent->color = RED;
		tmp = new->parent->parent;
		rbbalance(root,tmp);
	}
	else if((new->parent->left == new)&&(new->parent->parent->left == new->parent))
	{
		return rightrobate(root,new->parent);
	}
	else if((new->parent->right == new)&&(new->parent->parent->right== new->parent))
	{
		return leftrobate(root,new->parent);
	}
	else if((new->parent->right == new)&&(new->parent->parent->left == new->parent))
	{
		root = leftrobate(root,new);
		return rightrobate(root,new);
	}
	else if((new->parent->left==new)&&(new->parent->parent->right == new->parent))
	{
		root = rightrobate(root,new);
		return leftrobate(root,new);
	}
	
}

Rbpoint rbfind(Rbpoint root,int key)  //閫氳繃閿煡鎵炬爲涓殑鑺傜偣
{
	Rbpoint tmp = root;
	while(tmp->key != key)
	{
		if(tmp->key > key)
		{
			tmp = tmp->left;
			continue;
		}
		else
		{
			tmp = tmp->right;
			continue;
		}
	}
	return tmp;
}

Rbpoint findmin(Rbpoint root,Rbpoint right)   //鏌ユ壘鏍戜腑鐨勬渶灏忚妭鐐�
{
	if(right == sentinel)
		return root;
	Rbpoint tmp = right;
	while(tmp->left != sentinel)
		tmp = tmp->left;
	return tmp;
}

Rbpoint freenode(Rbpoint root,Rbpoint node)   //閲婃斁涓€涓妭鐐�
{
	if(node->parent == root)
		node->parent->right = node->right;
	else if(node->key > node->parent->key)
		node->parent->right = node->right;
	else
		node->parent->left = node->right;
	if(node->right != sentinel)
		node->right->parent = node->parent;
	free(node);
}

Rbpoint rbdelete(Rbpoint root,int key)   //鍒犻櫎涓€涓妭鐐�
{
	Rbpoint delz = rbfind(root,key);
	if((delz == root)&&(delz->left == delz->right))
	{
		free(root);
		return sentinel;
	}
	Rbpoint tmpy = findmin(delz,delz->right);
	Rbpoint tmpx;
	if(tmpy != delz)
		tmpx = tmpy->right;
	else
  	{
		tmpy->right = tmpy->left;
		tmpy->left = sentinel;
		tmpx = tmpy->right;
	}
	delz->key = tmpy->key;
        tmpy->key = key;
	Rbpoint tmp = tmpy->parent;
		
	if(tmpy->color == RED)
	{
		freenode(delz,tmpy);
		return root;
	}
			
	freenode(delz,tmpy);
	if((tmpx!=sentinel)&&(tmpx->color == RED))
	{
		tmpx->color = BLOCK;
		return root;
	}
	int flag = 1,color;
	Rbpoint tmpw ;
	Rbpoint tmpp ;
	while(flag)
	{

	       if(((tmpx == sentinel)&&(tmpx == tmp->left))||((tmpx != sentinel)&&(tmpx->key < tmpx->parent->key)))
		{
			if(tmpx == sentinel)
               	 	{
                        	tmpw = tmp->right;
                        	tmpp = tmp;
                	}
			else
			{
				tmpw = tmpx->parent->right;
       		 		tmpp = tmpx->parent;
			}
			if(tmpw->color == RED)
			{
				tmpw->color = BLOCK;
				tmpp->color = RED;
				root = leftrobate(root,tmpw);
				continue;
			}
			if((tmpw->color == BLOCK)&&(tmpw->right!=sentinel)&&(tmpw->right->color == RED))
			{
				color = tmpw->color;
				tmpw->color = tmpp->color;
				tmpp->color = color;
				tmpw->right->color = BLOCK;
				root = leftrobate(root,tmpw);
				return root;
			}
			if((tmpw->color == BLOCK)&&(tmpw->left!=sentinel)&&(tmpw->left->color==RED)&&(tmpw->right!=sentinel)&&(tmpw->right->color==BLOCK))
			{
				color = tmpw->color;
				tmpw->color = tmpw->left->color;
				tmpw->left->color = color;
				root  = rightrobate(root,tmpw->left);
				continue;
			}
			if(tmpw->color == BLOCK)
			{
				tmpw->color = RED;
				if(tmpp->color == RED)
				{
					tmpp->color = BLOCK;
					return root;
				}
				if(tmpp->parent == sentinel)
					return root;
				tmpx = tmpw->parent;
				continue;
			}
		}
		else
		{
			if(tmpx != sentinel)
			{
				tmpw = tmpx->parent->left;
       		 		tmpp = tmpx->parent;
			}
			else
			{
				tmpw = tmp->left;
				tmpp = tmp;
			}
			if(tmpw->color == RED)
			{
				tmpw->color = BLOCK;
				tmpp->color = RED;
				root = rightrobate(root,tmpw);
				continue;
			}
			if((tmpw->color == BLOCK)&&(tmpw->left!=sentinel)&&(tmpw->left->color == RED))
			{
				color = tmpw->color;
				tmpw->color = tmpp->color;
				tmpp->color = color;
				tmpw->left->color = BLOCK;
				root = rightrobate(root,tmpw);
				return root;
			}
			if((tmpw->color == BLOCK)&&(tmpw->left!=sentinel)&&(tmpw->left->color==BLOCK)&&(tmpw->right!=sentinel)&&(tmpw->right->color==RED))
			{
				color = tmpw->color;
				tmpw->color = tmpw->right->color;
				tmpw->right->color = color;
				root = leftrobate(root,tmpw->right);
				continue;
			}
			if(tmpw->color == BLOCK)
			{
				tmpw->color = RED;
				if(tmpp->color == RED)
				{
					tmpp->color = BLOCK;
					return root;
				}
				if(tmpp->parent == sentinel)
					return root;
				tmpx = tmpw->parent;
				continue;
			}
		}
	}
}

void  testpc(Rbpoint root,Rbpoint test)
{
	if(test == root)
		return ;
	if(test->key > test->parent->key)
	{
		if(test->parent->right != test)
		{
			printf("insert err %d\n",test->key);
			exit(0);
		}
	}
	else
	{
		if(test->parent->left != test)
		{
			printf("insert err %d\n",test->key);
			exit(0);
		}
	}
}

void midroot(Rbpoint root)   //鍏堟牴閬嶅巻
{
	if(root!=sentinel)
		printf("%d(%d),",root->key,root->color);
	if(root->left!=sentinel)
		midroot(root->left);
	if(root->right!=sentinel)
		midroot(root->right);
	//printf("\n");
}

int main(int argc,char **argv)
{
	
        sentinel = (Rbpoint)malloc(sizeof(Rbnode));
	printf("test createnode...\n");
	Rbpoint root = createroot(1);
	printf("test.key:%d,test.color:%d\n***************\n",root->key,root->color);
	printf("test insert....\n");
	Rbpoint test = createnode(2);
	root = rbinsert(root,test);
	int keytest[10000];
	int i;
	for(i=5;i<1000;i++)
	{
		test = createnode(i);
		root = rbinsert(root,test);
		testpc(root,test);
	}
	
	firstroot(root);
	midroot(root);
	printf("test firstroot done:.....\n");
	for(i=10;i<450;i++)
	{
		root = rbdelete(root,i);
		firstroot(root);
		printf("\n");
		midroot(root);
		printf("\n");
	}
	printf("test firstroot:.....\n");
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值