红黑树(red_black_tree)的c语言实现

// red_black_tree.cpp : 定义控制台应用程序的入口点。
//
/*
 ** red_black_tree.cpp

**  主要功能:创建一颗红黑树

**  数据结构:基本的数据结构是使用双向链表(需要经常访问PARENT,GRANDPARENT and UNCLE)实现的二叉树
**  核心步骤:在插入时红黑树的3*2种状态

**  PARENT IS LEFT

**  case1:PARENT is red && UNCLE is red

**  case2: PARENT is red && UNCLE is black && x is RIGHTCHILD

**  case3: PARENT is red && UNCLE is black && x is LEFTCHILD
**  PARENT IS RIGHT

**  case4: <->case1

**  case5: <->case2

**  case6: <->case3
**
 */

#include "stdafx.h"

#include <stdio.h>
#include <stdlib.h>
#include <time.h>       /* time */

#define PARENT(X) X->parent

#define GRANDPARENT(X) X->parent->parent

#define UNCLE(X) (PARENT(X) == GRANDPARENT(X)->left ? GRANDPARENT(X)->right : GRANDPARENT(X)->left)

#define ISLEFT(X) (PARENT(X)->left == X ? 1 : 0)

#define ISRIGHT(X) (PARENT(X)->right == X ? 1 : 0)

typedef int key_t;



typedef struct node_t{
	key_t key;
	char color;
	struct node_t * left;
	struct node_t * right;
	struct node_t * parent;
};

typedef node_t node_t;

typedef struct rbt{
	node_t * root;
	int nodes;
};

typedef rbt rbtree;

rbtree *  init_rbtree();

node_t * get_empty_node();

node_t * make_node_key(key_t key);

int insert(rbtree * rbt_p, key_t key);

rbtree *  init_rbtree()
{
	rbtree * rbt_p = NULL;
	rbt_p = (rbtree *) malloc(sizeof(rbtree));
	rbt_p->root = NULL;
	rbt_p->nodes = 0;
	return rbt_p;
}

node_t * get_empty_node()
{
	node_t * result = NULL;
	result = (node_t *)malloc(sizeof(node_t));
	result->key = -1;
	result->color = 'R';
	result->left = NULL;
	result->right = NULL;
	result->parent = NULL;
	return result;
}

node_t * make_node_key(key_t key)
{       
	node_t * result = NULL;
	result = (node_t *)malloc(sizeof(node_t));
	result->key = key;
	result->color = 'R';
	result->left = NULL;
	result->right = NULL;
	result->parent = NULL; 
	return result;
}

node_t * insert(node_t * root, key_t key)
{
	
	node_t * tmp_node = NULL;
	
	if(root == NULL)
	{
		tmp_node = make_node_key(key);
		return tmp_node;
	}

	if(key < root->key)
	{
		if(root->left == NULL)
		{
			tmp_node = make_node_key(key);
			root->left = tmp_node;
			tmp_node->parent = root;
		}
		else
			tmp_node = insert(root->left, key);
	}
	else if(key >= root->key)
	{
		if(root->right == NULL)
		{
			tmp_node = make_node_key(key);
			root->right = tmp_node;
			tmp_node->parent = root;
		}
		else
			tmp_node = insert(root->right, key);
	}
	return tmp_node;
}

int left_rotate(node_t * node_x)
{
	node_t * tmp_node = NULL;

	tmp_node = PARENT(node_x);

	
	if(PARENT(tmp_node) != NULL)						//注意对根结点的特殊处理
	{	
		if(ISLEFT(PARENT(node_x)))						//需要根据父节点是左孩子还是右孩子,决定旋转之后的结点作为左孩子,还是又孩子插入
		{
			PARENT(tmp_node)->left = node_x;
		}
		else if(ISRIGHT(PARENT(node_x)))				//需要根据父节点是左孩子还是右孩子,决定旋转之后的结点作为左孩子,还是又孩子插入
		{
			PARENT(tmp_node)->right = node_x;
		}
	}
	PARENT(node_x) = PARENT(tmp_node);
	
	if(node_x->left != NULL)							//对于叶子结点不需要为其指定父节点,因为叶子结点是一个NULL,没有存储空间
		PARENT(node_x->left) = tmp_node;
	tmp_node->right = node_x->left;

	PARENT(tmp_node) = node_x;
	node_x->left = tmp_node;
	return 1;
}

int right_rotate(node_t * node_x)
{
	node_t * tmp_node = NULL;

	tmp_node = PARENT(node_x);

	tmp_node->left = node_x->right;
	if(node_x->right != NULL)
		PARENT(node_x->right) = tmp_node;

	if(PARENT(tmp_node) != NULL)									//注意对根结点的特殊处理
	{
		if(ISLEFT(PARENT(node_x)))									//需要根据父节点是左孩子还是右孩子,决定旋转之后的结点作为左孩子,还是又孩子插入
		{
			PARENT(tmp_node)->left = node_x;
		}
		else if(ISRIGHT(PARENT(node_x)))							//需要根据父节点是左孩子还是右孩子,决定旋转之后的结点作为左孩子,还是又孩子插入
		{
			PARENT(tmp_node)->right = node_x;
		}
	}
	PARENT(node_x) = PARENT(tmp_node);

	PARENT(tmp_node) = node_x;
	node_x->right = tmp_node;
	return 1;
}


node_t * adjust(node_t * node_x)
{
	node_t * root = NULL;
	if(node_x->parent == NULL)					// the node_x is root
	{
		node_x->color = 'B';
		root = node_x;
		return root;
	}
	
	while(node_x->parent->color == 'R')				//node_x->parent->color=='B'  garentee that the node_x's parent is not root.
	{
		if(ISLEFT(PARENT(node_x)))
		{
			if(UNCLE(node_x) != NULL && UNCLE(node_x)->color == 'R')
			{
				PARENT(node_x)->color = 'B';
				UNCLE(node_x)->color = 'B';
				GRANDPARENT(node_x)->color = 'R';
				node_x = GRANDPARENT(node_x);
			}
			else if(UNCLE(node_x) == NULL && ISRIGHT(node_x) == 1 || UNCLE(node_x) != NULL && UNCLE(node_x)->color == 'B' && ISRIGHT(node_x) == 1)
			{
				left_rotate(node_x);
				node_x = node_x->left;
			}
			else if(UNCLE(node_x) == NULL && ISLEFT(node_x) == 1 || UNCLE(node_x) != NULL && UNCLE(node_x)->color == 'B' && ISLEFT(node_x) == 1)
			{
				right_rotate(PARENT(node_x));
				PARENT(node_x)->color = 'B';
				PARENT(node_x)->right->color = 'R';
				if(GRANDPARENT(node_x) == NULL)
				{
					root = PARENT(node_x);
				}
			}
		}
		else if(ISRIGHT(PARENT(node_x)))
		{
			if(UNCLE(node_x) != NULL && UNCLE(node_x)->color == 'R')
			{
				PARENT(node_x)->color = 'B';
				UNCLE(node_x)->color = 'B';
				GRANDPARENT(node_x)->color = 'R';
				node_x = GRANDPARENT(node_x);
			}
			else if(UNCLE(node_x) == NULL && ISLEFT(node_x) == 1 || UNCLE(node_x) != NULL && UNCLE(node_x)->color == 'B' && ISLEFT(node_x) == 1)
			{
				right_rotate(node_x);
				node_x = node_x->right;
			}
			else if(UNCLE(node_x) == NULL && ISRIGHT(node_x) == 1 || UNCLE(node_x) != NULL && UNCLE(node_x)->color == 'B' && ISRIGHT(node_x) == 1)
			{
				left_rotate(PARENT(node_x));
				PARENT(node_x)->color = 'B';
				PARENT(node_x)->left->color = 'R';
				if(GRANDPARENT(node_x) == NULL)
				{
					root = PARENT(node_x);
				}
			}
		}

		if(PARENT(node_x) == NULL)
		{
			node_x->color = 'B';
			root = node_x;
			break;
		}
	}
	return root;
}

int insert_rbtree(rbtree * rbt_t, key_t key)
{
	node_t * tmp_node = NULL;
	node_t * node_x = NULL;
	node_t * root = NULL;
	if(rbt_t->root == NULL)
	{
		tmp_node = make_node_key(key);
		tmp_node->color = 'B';
		rbt_t->root = tmp_node;
		rbt_t->nodes ++;

	}
	else
	{
		node_x = insert(rbt_t->root, key);
		rbt_t->nodes ++;
		root = adjust(node_x);
		if(root != NULL)
			rbt_t->root = root;
	}
	return 1;
}


int _tmain(int argc, _TCHAR* argv[])
{
	rbtree * rbt_t = NULL;
	rbt_t = init_rbtree();
	int i, j;
	for(i=18; i>0; --i)
	{
		srand (time(NULL));
		j = rand();
		insert_rbtree(rbt_t, j%10);
	}
	return 1;
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值