红黑树的创建+线索化+性质检验+笔画输入法

本文红黑树的实现参考《算法导论》第二版。写此算法之前,发现网络上很多版本均存在这样那样的错误,于是就自己实现了一个,用于做中文输入法。

《导论》2的算法描述省略了很多情况,故不能直接拿来用。文中的代码已全部补齐。代码内容包括红黑树的创建(左旋,右旋,插入调整),中序线索化红黑树(参考严文敏的《数据结构》),及红黑树的性质检测。程序中读取的测试文件是笔画输入法的笔画笔顺及对应的汉字。

下面是源程序:

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

#define TRUE  1
#define FALSE 0
#define HANZINUM 4762
#define HANZILENGTH 4
#define BIHUALENGTH 30

char bihuaArr[HANZINUM][BIHUALENGTH];
char hanziArr[HANZINUM][4];
int first = 1;
int num = 0;

typedef struct bihuaData{
    char data[4];
    char bihua[30];
}bihuaData;

typedef int BOOL;
typedef bihuaData ElemType;
enum COLOR {Red, Black};
enum pointerTag {Link, Thread};

typedef struct RedBlackNode{
	ElemType data;
	struct RedBlackNode *left;
	struct RedBlackNode *right;
    struct RedBlackNode *p;
	char color;//Red, Black
    char ltag;
    char rtag;
}RedBlackNode, *RedBlackTree;

BOOL find(RedBlackTree root, const ElemType x);
void pprint(RedBlackTree root, int i);

void makeEmpty(RedBlackNode *t);
void left_rotate(RedBlackTree *t, RedBlackNode *x);
void right_rotate(RedBlackTree *t, RedBlackNode *x);
void rb_insert(RedBlackTree *root, RedBlackNode *t);
void rb_insert_fixup(RedBlackTree *root, RedBlackNode *z);
int compare(RedBlackNode *y, RedBlackNode *z);
void creat_rb_tree(RedBlackTree * root);
BOOL check_rb_tree(RedBlackTree root);
void check_black_num(RedBlackTree root, int n);
void inorder_traverse_rb_tree(RedBlackTree root);
void negative_inorder_traverse_rb_tree(RedBlackTree root);
void inorder_threading_rb_tree(RedBlackTree *thrt, RedBlackTree root);

int main(){
	RedBlackTree rbTree = NULL;
	creat_rb_tree(&rbTree);
	//check_rb_tree(rbTree);
}

void creat_rb_tree(RedBlackTree * root)
{
	FILE *fp = NULL;
	char *file = "./bihuabishun.txt";
    char *file3 = "./bihuahanzi.txt";
    int i;
    RedBlackNode *p = NULL;
    RedBlackTree thrt;
    freopen("data.out", "w", stdout);
    fp = fopen(file, "rb");
    if (fp == NULL)
    {
        printf("exit!\n");
        exit(0);
    }
    fread(bihuaArr, BIHUALENGTH, HANZINUM, fp);
    fclose(fp);
    fp = fopen(file3, "rb");
    if (fp == NULL)
    {
        printf("exit!\n");
        exit(0);
    }
    fread(hanziArr, 4, HANZINUM, fp);
    fclose(fp);
    
    for (i = 0 ; i < HANZINUM; i++)
    {
        if (strcmp(bihuaArr[i], "") != 0 && strcmp(hanziArr[i], "") != 0)
        {
        	p = (RedBlackNode *)malloc(sizeof(RedBlackNode));
        	if(p == NULL)
       		{
          	  printf("exit!\n");
           	 exit(0);
       	    }
        	memset(p, 0, sizeof(RedBlackNode));
        	strcpy(p->data.data, hanziArr[i]);
        	strcpy(p->data.bihua, bihuaArr[i]);
            rb_insert(root, p);
            if(i == 4760){
            	inorder_threading_rb_tree(&thrt, *root);
            	negative_inorder_traverse_rb_tree(thrt);
            }
        }
    }
}

void left_rotate(RedBlackTree *t, RedBlackNode *x)
{
	RedBlackNode * y = NULL;
	y = x->right;
	x->right = y->left;
	if(y->left != NULL)
	{
		y->left->p = x;
	}
	y->p = x->p;
	if(x->p == NULL)
	{
		*t = y;
	}
	else if(x == x->p->left)
	{
		x->p->left = y;	
	}
	else
	{
		x->p->right = y;
	}
	y->left = x;
	x->p = y;
}

void right_rotate(RedBlackTree *t, RedBlackNode *x)
{
	RedBlackNode * y = NULL;
	y = x->left;
	x->left = y->right;
	if(y->right != NULL)
	{
		y->right->p = x;
	}
	y->p = x->p;
	if(x->p == NULL)
	{
		*t = y;
	}
	else if(x == x->p->left)
	{
		x->p->left = y;	
	}
	else
	{
		x->p->right = y;
	}
	y->right = x;
	x->p = y;
}

void makeEmpty(RedBlackNode *t){
	if(t != NULL){
		makeEmpty(t->left);
		makeEmpty(t->right);
		free(t);
	}
	t = NULL;
}

void rb_insert(RedBlackTree *root, RedBlackNode *z)
{
	RedBlackNode *x = NULL, *y = NULL;
	
	y = NULL;
	x = *root;
	while(x != NULL)
	{
		y = x;
		if(compare(x, z) == 0)
		{
			return;
		}
		else if(compare(x, z) > 0)
		{
			x = x->left;
		}
		else if(compare(x, z) < 0)
		{
			x = x->right;
		}
	}
	z->p = y;
	if(y == NULL)
	{
		*root = z;
	}
	else if(compare(y, z) == 0)
	{
		return;
	}
	else if(compare(y, z) > 0)
	{
		y->left = z;
	}
	else if(compare(y, z) < 0)
	{
		y->right = z;
	}
	z->left = NULL;
	z->right = NULL;
	z->color = Red;
	rb_insert_fixup(root, z);
}

void pprint(RedBlackTree root, int i){
	if(root){
		if(root->p != NULL)	
{
num = num > i? num : i;}
		pprint(root->left, i+1);
		pprint(root->right, i+1);
	}
}

int compare(RedBlackNode *y, RedBlackNode *z)
{
	if(strlen(y->data.bihua) ==  strlen(z->data.bihua))
	{
		return strcmp(y->data.bihua, z->data.bihua);
	}
	return strlen(y->data.bihua) - strlen(z->data.bihua);
}

void rb_insert_fixup(RedBlackTree *root, RedBlackNode *z)
{
	RedBlackNode *y = NULL;
	while(z->p != NULL && z->p->color == Red)
	{
		if(z->p == z->p->p->left)
		{
			y = z->p->p->right;
			if(y == NULL)
			{
				if( z == z->p->right)
				{
					z = z->p;
					left_rotate(root, z);
					z->p->color = Black;
					z->p->p->color = Red;
					right_rotate(root, z->p->p);	
				}
				else if( z == z->p->left)
				{
					z->p->color = Black;
					z->p->p->color = Red;
					right_rotate(root, z->p->p);
					return;
				}	
			}
			else
			{
				if(y->color == Red)
				{
					z->p->color = Black;
					y->color = Black;
					z->p->p->color = Red;
					z = z->p->p;
				}
				else 
				{
					if( z == z->p->right)
					{
						z = z->p;
						left_rotate(root, z);
					}
					z->p->color = Black;
					z->p->p->color = Red;
					right_rotate(root, z->p->p);	
				}		
			}
		}
		else
		{
			y = z->p->p->left;
			if(y == NULL)
			{	
				if( z == z->p->right)
				{
					z->p->color = Black;
					z->p->p->color = Red;
					left_rotate(root, z->p->p);
					return;
				}
				else if( z == z->p->left)
				{
					z = z->p;
					right_rotate(root, z);
					z->p->color = Black;
					z->p->p->color = Red;
					left_rotate(root, z->p->p);	
				}
			}
			else
			{
				if(y->color == Red)
				{
					z->p->color = Black;
					y->color = Black;
					z->p->p->color = Red;
					z = z->p->p;
				}
				else
				{
					if( z == z->p->left)
					{
						z = z->p;
						right_rotate(root, z);
					}
					z->p->color = Black;
			    	z->p->p->color = Red;
			    	left_rotate(root, z->p->p);
				}
			}
		}
	}
	(*root)->color = Black;
}

void check_rb_tree_child(RedBlackTree root, int i)
{
	if(root->color == Red && root->left != NULL && root->right != NULL)
	{
		if(root->left->color == Black && root->right->color == Black)
		{
		}
		else printf("9\n");
	}
	
	if(root->left != NULL)
	{
		check_rb_tree_child(root->left, i + 1);
	}
	if(root->right != NULL)
	{
		check_rb_tree_child(root->right, i + 1);
	}
}

BOOL check_rb_tree(RedBlackTree root)
{
	int i = 0;
	if(root->color == Red)
	{
		printf("root ERR!\n");
		return 1;
	}
	check_rb_tree_child(root, ++i);
	return 0;
}

void check_black_num(RedBlackTree root, int n)
{
	if(root == NULL)
	{
		printf("%d  \n", n);	
	}else
	{
		if(root->color == Black)
		{
			n+=1;
		}
		check_black_num(root->left, n);
		check_black_num(root->right, n);	
	}
}

void inorder_traverse_rb_tree(RedBlackTree root)
{
	RedBlackNode *p = NULL;
	
	p = root->left;
	
	while(p != root)
	{
		while(p->ltag == Link)
		{
			p = p->left;
		}
		printf("%s\n",p->data.bihua);
		while(p->rtag == Thread && p->right != root)
		{
			p = p->right;
			printf("%s\n",p->data.bihua);
		}
		p = p->right;
	}
}

void negative_inorder_traverse_rb_tree(RedBlackTree root)
{
	RedBlackNode *p = NULL;
	
	p = root->right;
	
	while(p != root)
	{
		while(p->rtag == Link)
		{
			p = p->right;
		}
		printf("%s\n",p->data.bihua);
		while(p->ltag == Thread && p->left != root)
		{
			p = p->left;
			printf("%s\n",p->data.bihua);
		}
		p = p->left;
	}
}

void InThreading(RedBlackTree p, RedBlackTree * pre)
{
	if(p)
	{
		InThreading(p->left, pre);
		if(p->left == NULL)
		{
			p->ltag = Thread;
			p->left = *pre;
		}
		if((*pre)->right == NULL)
		{
			(*pre)->rtag = Thread;
			(*pre)->right = p;
		}
		(*pre) = p;
		InThreading(p->right, pre);
	}
}

void inorder_threading_rb_tree(RedBlackTree *thrt, RedBlackTree root)
{
	RedBlackNode * pre = NULL;
	
	*thrt = (RedBlackNode *)malloc(sizeof(RedBlackNode));
	if(*thrt == NULL)
	{
  	  printf("exit!\n");
   	 exit(0);
    }
	memset(*thrt, 0, sizeof(RedBlackNode));
	
	(*thrt)->ltag = Link;
	(*thrt)->rtag = Thread;
	(*thrt)->right = (*thrt);
	if(root == NULL)(*thrt)->left = (*thrt);
	else
	{
		(*thrt)->left = root;
		pre = (*thrt);
		InThreading(root, &pre);
		pre->right = (*thrt);
		pre->rtag = Thread;
		(*thrt)->right = pre;
	}	
}
点赞