main.c
#include <stdio.h>
#include <stdlib.h>
#include "rbtree.h"
void show_menu(void){
printf("*******(红黑树功能测试)**********\n");
printf("**1. 插入元素 \n");
printf("**2. 删除元素 \n");
printf("**4. 树是否为空 \n");
printf("**5. 树中元素个数 \n");
printf("**6. 树的高度 \n");
printf("**7. 树的先序遍历 \n");
printf("**8. 树的中序遍历 \n");
printf("**9. 树的后序遍历 \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:
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:
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;
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.c
#include "rbtree.h"
#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;
node->lchild = NULL;
node->rchild = NULL;
node->parent = parent;
}
}
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->parent->lchild = right;
}else{
node->parent->rchild = right;
}
}else{
*proot = right;
}
node->rchild = right->lchild;
if(right->lchild!=NULL)
right->lchild->parent = node;
right->lchild = node;
node->parent = 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;
}
static void rbtree_insert_repair(RBTree *proot,struct RBNode *node){
struct RBNode *parent = node->parent;
while(node->color == RED && (parent!=NULL && parent->color == RED)){
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;
}
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;
}
rbtree_insert_repair(proot,*ptree);
return 0;
}
static void rbtree_delete_repair(RBTree *proot,struct RBNode *parent,
struct RBNode *node){
while(parent!=NULL && (node==NULL || node->color==BLACK)){
struct RBNode *brother = parent->lchild==node?parent->rchild:parent->lchild;
if(node == parent->lchild){
if(brother->color==RED){
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{
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)){
if(parent->color == RED){
parent->color = BLACK;
brother->color = RED;
break;
}else{
brother->color = RED;
node = parent;
parent = node->parent;
continue;
}
}
if(ISBLACK(brother->lchild)){
brother->color = RED;
brother->rchild->color = BLACK;
left_rotate(proot,brother);
brother = brother->parent;
}
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;
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);
}
}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{
*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;
while(*ptree != NULL){
if(elem == (*ptree)->elem){
rbtree_delete_node(proot,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)是黑色 这里的叶子结点是不存在的结点,指为空
如果一个结点是红色的,那么它的子结点必须是黑色的
即不能有两个连续的红色结点
从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点
最长的路径不大于最短路径的两倍(大致上是平衡的)
保证局部的平衡