红黑树的系列函数

快捷跳转

main.c

#include <stdio.h>
#include <stdlib.h>
#include "rbtree.h" 

void show_menu(void){
	printf("*******(红黑树功能测试)**********\n");
	printf("**1. 插入元素 \n");
	printf("**2. 删除元素 \n");
//	printf("**3. 查找某元素是否在树中 \n");
	printf("**4. 树是否为空 \n");
	printf("**5. 树中元素个数 \n");
	printf("**6. 树的高度 \n");
	printf("**7. 树的先序遍历 \n");
	printf("**8. 树的中序遍历 \n");
	printf("**9. 树的后序遍历 \n");
//	printf("**10.树的层序遍历 \n");
	printf("**11. 清空树 \n");
	printf("**0. 退出 \n");
	printf(">>>>");
}

void travel(ETYPE val,char color){
	printf("%d(%s) ",val,color==RED?"RED":"BLACK");
}

void test_rb_tree(void){
	RBTree tree = NULL;
	rbtree_init(&tree);
	while(true){
		show_menu();
		int opt = 0;
		int elem = 0;
		int ret = 0;
		bool f = true;
		scanf("%d",&opt);
		switch(opt){
			case 1:
				printf("请输入要插入二叉排序树中的元素:");
				scanf("%d",&elem);
				ret = rbtree_insert(&tree,elem);
				if(ret == 0){
					printf("插入成功!\n");
				}else{
					if(ret == -1){
						printf("树中已有该元素,插入失败!\n");
					}else{
						printf("插入失败!内存问题!\n");
					}
				}
				break;
			case 2:
				printf("请输入要删除的元素:");
				scanf("%d",&elem);
				ret = rbtree_delete(&tree,elem);
				if(ret == 0){
					printf("删除成功!\n");
				}else{
					printf("删除失败!树中没有该元素!\n");
				}
				break;
			case 3:
//				printf("请输入要查找树中是否存在的元素:");
//				scanf("%d",&elem);
//				if(val_tree_contains(tree,elem)){
//					printf("树中存在该元素!\n");
//				}else{
//					printf("树中没有该元素!\n");
//				}
				break;
			case 4:
				rbtree_empty(tree)?puts("空空如也!\n"):puts("树中有元素!\n");
			case 5:
				printf("树中元素个数:%u\n",rbtree_size(tree));
			case 6:
				printf("树的高度为:%u\n",rbtree_hight(tree));
				break;
			case 7:
				rbtree_front_travel(tree,travel);
				printf("\n");
			case 8:
				rbtree_mid_travel(tree,travel);
				printf("\n");
			case 9:
				rbtree_back_travel(tree,travel);
				printf("\n");
			case 10:
				//rbtree_layer_travel(tree,travel);
				printf("\n");
				break;
			case 11:
				rbtree_clear(&tree);
				break;
			case 0:
				rbtree_destroy(&tree);
				return; 
		}
	}
}

int main(int argc, char *argv[]) {
	test_rb_tree();
	return 0;
}

rbtree.h

#ifndef _RBTREE_H__
#define _RBTREE_H__

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef int ETYPE;
enum COL{RED=0,BLACK=1}; 
typedef struct RBNode{
	ETYPE elem;
	char color;             //颜色   RED  BLACK 
	struct RBNode *lchild;
	struct RBNode *rchild;
	struct RBNode *parent;  //记录父结点 
}RBNode;
typedef struct RBNode * RBTree;

int rbtree_insert(RBTree *proot,ETYPE elem);
int rbtree_delete(RBTree *proot,ETYPE elem);

void rbtree_init(RBTree *proot);
bool rbtree_empty(RBTree root);
size_t rbtree_size(RBTree root);
size_t rbtree_hight(RBTree root);

void rbtree_front_travel(RBTree root,void (*travel)(ETYPE,char));
void rbtree_mid_travel(RBTree root,void (*travel)(ETYPE,char));
void rbtree_back_travel(RBTree root,void (*travel)(ETYPE,char));
void rbtree_clear(RBTree *proot);
void rbtree_destroy(RBTree *proot);
#endif //_RBTREE_H__ 

rbtree.c

#include "rbtree.h"
/*
typedef int ETYPE;
enum COL{RED=0,BLACK=1}; 
typedef struct RBNode{
	ETYPE elem;
	char color;             //颜色   RED  BLACK 
	struct RBNode *lchild;
	struct RBNode *rchild;
	struct RBNode *parent;  //记录父结点 
}RBNode;
typedef struct RBNode * RBTree;
*/

#define ISBLACK(node) (node==NULL||node->color==BLACK)

static struct RBNode *rbtree_create_node(ETYPE elem,struct RBNode *parent){
	struct RBNode *node = (struct RBNode*)malloc(sizeof(struct RBNode));
	if(node!=NULL){
		node->elem = elem;
		node->color = RED;//插入的结点都是红色  保证了红黑树5的特性  可能会违反性质3
		node->lchild = NULL;
		node->rchild = NULL; 
		node->parent = parent;
	}
}

//对node结点进行左旋  
/*
          ||                                  ||
        node                                right 
        /  \                               //   \
      left  right    node左旋            node   rr
            /  \                         /  \\
           rl  rr                      left  rl
*/
static void left_rotate(RBTree *proot,struct RBNode *node){
	struct RBNode *right = node->rchild;
	right->parent = node->parent;
	if(node->parent!=NULL){
		if(node == node->parent->lchild){//node是父结点的左孩子 
			node->parent->lchild = right;
		}else{//node是父结点的右孩子 
			node->parent->rchild = right;
		}
	}else{//node的父结点不存在 说明 node本来是根结点   right作为根结点 
		*proot = right;
	}
	node->rchild = right->lchild;
	if(right->lchild!=NULL)
		right->lchild->parent = node;
	right->lchild = node;
	node->parent = right;
} 
//对node结点进行右旋
/*
          |                                  |
        node                                left 
        /  \                               /    \
      left  right    node右旋            ll     node
      /  \                                      /  \
     ll  lr                                    lr   right
*/
static void right_rotate(RBTree *proot,struct RBNode *node){
	struct RBNode *left = node->lchild;
	left->parent = node->parent;
	if(node->parent!=NULL){
		if(node == node->parent->lchild){
			node->parent->lchild = left;
		}else{
			node->parent->rchild = left;
		}
	}else{
		*proot = left;
	}
	node->lchild = left->rchild;
	if(left->rchild!=NULL)
		left->rchild->parent = node;
	node->parent = left;
	left->rchild = node;
} 

//*proot指向根结点   node为新插入的结点 
static void rbtree_insert_repair(RBTree *proot,struct RBNode *node){
	//node是当前结点得是红色  parent 
	struct RBNode *parent = node->parent;
	//两个连续红色的结点 
	while(node->color == RED && (parent!=NULL && parent->color == RED)){
		//node为红  parent为红  
		struct RBNode *gp = parent->parent;   //祖父结点
		struct RBNode *uncle = gp->lchild==parent?gp->rchild:gp->lchild;
		if(uncle!=NULL && uncle->color==RED){//叔叔为红 
			parent->color = BLACK;
			uncle->color = BLACK;
			gp->color = RED;
			node = gp;//把祖父置红之后 需要继续向上讨论 
			parent = node->parent; 
		}else{//叔叔为黑 
			if(parent==gp->lchild){//父为左  叔为右 
				if(node==parent->rchild){//自己为右 
					left_rotate(proot,parent);//左旋之后  父结点变成左孩子 
					node = parent;
					parent = node->parent; 
				} 
				//自己为左 node == parent->lchild
				right_rotate(proot,gp);
				gp->color = RED;
				parent->color = BLACK; 
			}else{//父为右   叔为左 
				if(node==parent->lchild){//自己为左 
					right_rotate(proot,parent);
					node = parent;
					parent = node->parent; 
				}
				//自己为右
				left_rotate(proot,gp);
				gp->color = RED;
				parent->color = BLACK; 
			}
			break;
		}
	}
	(*proot)->color = BLACK;  //根结点一定是黑色的 
} 
int rbtree_insert(RBTree *proot,ETYPE elem){
	struct RBNode **ptree = proot; //记录了根结点 
	struct RBNode *parent = NULL;
	while(*ptree != NULL){
		parent = *ptree;
		if(elem < (*ptree)->elem){
			ptree = &(*ptree)->lchild;
		}else if(elem > (*ptree)->elem){
			ptree = &(*ptree)->rchild;
		}else{
			return -1;
		}
	}
	*ptree = rbtree_create_node(elem,parent);
	if(*ptree == NULL){
		return -2;
	}
	//对红黑树进行修复 *proot是根结点  *ptree新插入的结点 
	rbtree_insert_repair(proot,*ptree);
	return 0;
}

static void rbtree_delete_repair(RBTree *proot,struct RBNode *parent,
	struct RBNode *node){
	//修复   相当于 parent 所指向的node结点方向删除了一个黑色结点
	//node结点必须兄弟结点 
	while(parent!=NULL && (node==NULL || node->color==BLACK)){
		//兄弟 
		struct RBNode *brother = parent->lchild==node?parent->rchild:parent->lchild;
		if(node == parent->lchild){//删除的是parent结点的左孩子 
			if(brother->color==RED){//case 1 兄弟为红    父为黑  兄弟的孩子为黑 
				brother->color = BLACK;
				parent->color = RED;
				left_rotate(proot,parent);
				brother = parent->rchild; 
			} 
			//兄弟为黑  且兄弟不存在红色的孩子 
			if(ISBLACK(brother)&&ISBLACK(brother->lchild)&&ISBLACK(brother->rchild)){
				if(parent->color==RED){//父结点为红色 
					parent->color = BLACK;
					brother->color = RED;
					break;//结束了 
				}else{//父结点是黑色的 
					brother->color = RED;
					node = parent;
					parent = parent->parent;
					continue; 
				} 
			}
			//兄弟存在红色的孩子
			if(ISBLACK(brother->rchild)){//远端侄子不是黑的  近端是红的 
				brother->color = RED;
				brother->lchild->color = BLACK;
				right_rotate(proot,brother);
				brother = brother->parent; 
			} 
			//远端的侄子是红色的
			brother->color = parent->color;
			parent->color = BLACK;
			brother->rchild->color = BLACK;
			left_rotate(proot,parent);
			break; 
		}else{//删除的是parent结点的右孩子 
			//兄弟为红
			if(brother->color == RED){
				parent->color = RED;
				brother->color = BLACK;
				right_rotate(proot,parent);
				brother = parent->lchild;
			} 
			//兄弟为黑
			if(ISBLACK(brother) && ISBLACK(brother->lchild) 
				&& ISBLACK(brother->rchild)){//1.兄弟儿子都为黑
			    if(parent->color == RED){ //   a.父结点为红
			    	parent->color = BLACK;
			    	brother->color = RED;
			    	break;
				}else{//   b.父结点为黑 
					brother->color = RED;
					node = parent;
					parent = node->parent;
					continue;
				}	
			}
			//2.兄弟儿子不全为黑
			//   a.远端为黑(近端为红) 
			if(ISBLACK(brother->lchild)){
				brother->color = RED;
				brother->rchild->color = BLACK;
				left_rotate(proot,brother);
				brother = brother->parent;
			}  
			//   b.远端为红 
			brother->color = parent->color;
			parent->color = BLACK;
			brother->lchild->color = BLACK;
			right_rotate(proot,parent);
			break;
		}
	} 
} 

static void rbtree_delete_node(RBTree *proot,struct RBNode **pnode){
	struct RBNode *node = *pnode;//node结点是要删除的结点 
	if(node->lchild==NULL && node->rchild==NULL){//叶子结点 
		if(node->color == RED){
			*pnode = NULL;
			free(node);
		}else{//删除黑色结点
			struct RBNode *parent = node->parent;//记录父结点 
			*pnode = NULL; 
			free(node);
			rbtree_delete_repair(proot,parent,NULL);//NULL表示删除的结点 
		}
	}else if(node->lchild!=NULL && node->rchild!=NULL){//有两个子树 
		//找左子树最大值 替换 当前结点的值  然后去删除左子树中的最大值 
		for(pnode=&(*pnode)->lchild;(*pnode)->rchild!=NULL;pnode=&(*pnode)->rchild);
		node->elem = (*pnode)->elem; //用左子树中的最大值来替换
		rbtree_delete_node(proot,pnode); //去删除左子树中的最大值结点 
	}else{//只有一个子树  且子树为红   node结点是黑的 
		*pnode = node->lchild!=NULL?node->lchild:node->rchild;
		(*pnode)->color = BLACK;
		(*pnode)->parent = node->parent;
		free(node); 
	} 	
} 
int rbtree_delete(RBTree *proot,ETYPE elem){
	RBTree *ptree = proot;//*proot
	while(*ptree != NULL){
		if(elem == (*ptree)->elem){
			rbtree_delete_node(proot,ptree);//删除*ptree结点 
			return 0; 
		}else if(elem < (*ptree)->elem){
			ptree = &(*ptree)->lchild;
		}else{
			ptree = &(*ptree)->rchild;
		}
	}
	return -1;
}


void rbtree_init(RBTree *proot){
	*proot = NULL;
}
bool rbtree_empty(RBTree root){
	return root == NULL;
}
size_t rbtree_size(RBTree root){
	if(root == NULL)
		return 0;
	return 1+rbtree_size(root->lchild)+rbtree_size(root->rchild);
}
size_t rbtree_hight(RBTree root){
	if(root == NULL)
		return 0;
	size_t lh = rbtree_hight(root->lchild)+1;
	size_t rh = rbtree_hight(root->rchild)+1;
	return lh>rh?lh:rh;
}

void rbtree_front_travel(RBTree root,void (*travel)(ETYPE,char)){
	if(root!=NULL){
		travel(root->elem,root->color);
		rbtree_front_travel(root->lchild,travel);
		rbtree_front_travel(root->rchild,travel);
	}
}
void rbtree_mid_travel(RBTree root,void (*travel)(ETYPE,char)){
	if(root!=NULL){
		rbtree_mid_travel(root->lchild,travel);
		travel(root->elem,root->color);
		rbtree_mid_travel(root->rchild,travel);
	}
}
void rbtree_back_travel(RBTree root,void (*travel)(ETYPE,char)){
	if(root!=NULL){
		rbtree_back_travel(root->lchild,travel);
		rbtree_back_travel(root->rchild,travel);
		travel(root->elem,root->color);
	}
}
void rbtree_clear(RBTree *proot){
	if(*proot != NULL){
		rbtree_clear(&(*proot)->lchild);
		rbtree_clear(&(*proot)->rchild);
		free(*proot);
		*proot = NULL;
	}
}
void rbtree_destroy(RBTree *proot){
	rbtree_clear(proot);
}


R-B tree 红黑树
特性:
每个结点或者黑色或者红色
根结点是黑色
每个叶子结点(NIL)是黑色      这里的叶子结点是不存在的结点,指为空 
如果一个结点是红色的,那么它的子结点必须是黑色的
即不能有两个连续的红色结点
从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点
最长的路径不大于最短路径的两倍(大致上是平衡的)

保证局部的平衡
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值