通用AVLTree

算法描述:

在平衡的二叉排序樹T上插入一個關鍵碼爲kx的新元素,遞歸算法可描述如下:

㈠ 若T爲空樹,則插入一個數據元素爲kx的新結點作爲T的根結點,樹的深度增1;

㈡ 若kx和T的根結點關鍵碼相等,則不進行插入;

㈢ 若kx小於T的根結點關鍵碼,而且在T的左子樹中不存在與kx有相同關鍵碼的結點,則將新元素插入在T的左子樹上,並且當插入 之後的左子樹深度增加1時,分別就下列情況進行處理:

⑴ T的根結點平衡因子爲-1(右子樹的深度大於左子樹的深度),則將根結點的平衡因子更改爲0,T的深度不變;

⑵ T的根結點平衡因子爲0(左、右子樹的深度相等),則將根結點的平衡因子更改爲1,T的深度增加1;

⑶ T的根結點平衡因子爲1(左子樹的深度大於右子樹的深度),則若T的左子樹根結點的平衡因子爲1,需進行單向右旋平衡處理並且在右旋 處理之後,將根結點和其右子樹根結點的平衡因子更改爲0,樹的深度不變;若T的左子樹根結點平衡因子爲-1,需進行先左後右 雙向旋轉平衡處理,並且 在旋轉處理之後,修改根結點和其左、右子樹根結點的平衡因子,樹的深度不變。

㈣ 若kx大於T的根結點關鍵碼,而且在T的右子樹中不存在與kx有相同關鍵碼的結點,則將新元素插入在T的右子樹上並且當插入之後的右子樹深度增加1時,分別就不同情況處理之。其處理操作和 ㈢ 中所述相對稱。

動畫演示:

http://www.cnblogs.com/abatei/archive/2008/11/17/1335031.html

牛人博客一篇,完美的對稱化:

http://blog.csdn.net/happycock/article/details/20874

code:

/*
*設計思路:
1.通過void *表示任意類型的數據
2.通過爲插入函數提供比較函數,實現任意數據的插入
3.本頭文件實現的是適合任意類型的平衡二叉樹的數據結構,目前僅支持字符串和整型數據的平衡二叉樹;
若需要其他類型,定義相關的比較函數即可;
4.平衡二叉樹構造的基本思想:節點的平衡因子只能是-1,0,1;在插入造成不平衡時,需要對距離插入節點最近的不平衡節點做旋轉處理,上面的則不作處理;
5.插入的基本操作是左旋和右旋,左右旋和右左旋也能劃分爲這兩種操作,關鍵在於旋轉後平衡因子的確定
*/
#include <stdlib.h>
#include <string.h>

#define LH 1
#define EH 0
#define RH -1
typedef int (*COMPARE_FUNC)(void *, void *);

typedef struct avlnode{
	void *data;
	struct avlnode *lchild, *rchild;
	int bf;
}AVLNode, *AVLTree;

int compare_string(void *str1, void *str2)
{//call back func
	char *s1 = (char *)str1;
	char *s2 = (char *)str2;

	return strcmp(s1,s2);
}
int compare_int(void *var1, void *var2)
{
	int v1 = *(int *)var1;
	int v2 = *(int *)var2;

	return v1 - v2;
}
void R_Rotate(AVLTree *root)
{//向右旋轉,適合LL型
	AVLTree lchild = (*root)->lchild;

	(*root)->lchild = lchild->rchild;
	lchild->rchild = *root;
	*root = lchild;
}
void L_Rotate(AVLTree *root)
{
	AVLTree rchild = (*root)->rchild;

	(*root)->rchild = rchild->lchild;
	rchild->lchild = *root;
	(*root) = rchild;
}
void RightBalance(AVLTree *root)
{//bf == -2
	AVLTree rchild = (*root)->rchild;
	AVLTree rlchild;

	switch(rchild->bf)
	{
	case RH:
		rchild->bf = EH;
		(*root)->bf = EH;
		L_Rotate(root);
		break;
	case LH:
		rlchild = rchild->lchild;
		switch(rlchild->bf)
		{
		case RH:
			(*root)->bf = LH;
			rchild->bf = EH;
			break;
		case EH:
			(*root)->bf = EH;
			rchild->bf = EH;
			break;
		case LH:
			(*root)->bf = EH;
			rchild->bf = RH;
			break;
		}
		rlchild->bf = EH;
		R_Rotate(&((*root)->rchild));
		L_Rotate(root);
	default:
		break;
	}
}
void LeftBalance(AVLTree *root)
{//bf == 2
	AVLTree lchild = (*root)->lchild;
	AVLTree lrchild;

	switch(lchild->bf)
	{
	case LH://LL型 root bf 2 lchild bf 1
		lchild->bf = EH;
		(*root)->bf = EH;
		R_Rotate(root);
		break;
	case RH://LR型
		lrchild = lchild->rchild;
		switch(lrchild->bf)
		{
		case LH:
			(*root)->bf = RH;
			lchild->bf = EH;
			break;
		case EH:
			(*root)->bf = EH;
			lchild->bf = EH;
			break;
		case RH:
			(*root)->bf = EH;
			lchild->bf = LH;
			break;
		}
		lrchild->bf = EH;
		L_Rotate(&((*root)->lchild));
		R_Rotate(root);
	default:
		break;
	}
}
int shorter = 0;
void RightBalanceD(AVLTree *root)
{
	AVLTree rchild = (*root)->rchild;
	AVLTree rlchild;

	switch(rchild->bf)
	{
		case RH:
			(*root)->bf = rchild->bf = EH;
			R_Rotate(root);
			break;
		case EH:
			(*root)->bf = RH;
			rchild->bf = RH;
			L_Rotate(root);
			shorter = 0;
			break;
		case LH:
			rlchild = rchild->lchild;
			switch(rlchild->bf)
			{
				case LH:
					(*root)->bf = LH;
					rchild->bf = EH;
					break;
				case EH:
					(*root)->bf = EH;
					rchild->bf = EH;
					break;
				case RH:
					(*root)->bf  = EH;
					rchild->bf = RH;
					break;
			}
			rlchild->bf = EH;
			R_Rotate(&((*root)->rchild));
			L_Rotate(root);
	}
}
void LeftBalanceD(AVLTree *root)
{
	AVLTree lchild = (*root)->lchild;
	AVLTree lrchild;

	switch(lchild->bf)
	{
		case LH:
			(*root)->bf = lchild->bf = EH;
			R_Rotate(root);
			break;
		case EH:
			(*root)->bf = LH;
			lchild->bf = RH;
			R_Rotate(root);
			break;
		case RH:
			lrchild = lchild->rchild;
			switch(lrchild->bf)
			{
				case RH:
					(*root)->bf = EH;
					lchild->bf = EH;
					shorter = 0;
					break;
				case EH:
					(*root)->bf = EH;
					lchild->bf = EH;
					shorter = 1;
					break;
				case LH:
					(*root)->bf  = RH;
					lchild->bf = EH;
					shorter = 1;
					break;
			}
			lrchild->bf = EH;
			L_Rotate(&((*root)->lchild));
			R_Rotate(root);
	}
}
int AVLDelete(AVLTree *root, void *data, COMPARE_FUNC compare)
{
	int success = 0;
	int ret;

	if(NULL != *root)
	{
		ret = compare(data, (*root)->data);
		if( ret == 0)
		{			
			if(NULL != (*root)->lchild && NULL != (*root)->rchild)
			{
				AVLTree q,r;
				void *temp;

				//將左子樹的最下面的右子樹作爲其替身,然後刪掉,遞歸進行
				q = (*root)->lchild;
				r = q;
				while(q)
				{
					r = q;
					q = q->rchild;
				}
				temp = (*root)->data;
				(*root)->data = r->data;
				r->data =temp;

				AVLDelete(&(*root)->lchild, data, compare);
				if(1 == shorter)
				{
					switch((*root)->bf)
					{
					case LH:
						(*root)->bf = EH;
						break;
					case EH:
						(*root)->bf = RH;
						break;
					case RH:
						RightBalanceD(root);
						break;
					}//switch
				}//if  shorter
			}//if NULL
			else
			{
				//至少有一個子樹爲空
				AVLTree p = *root;

				*root = ((*root)->lchild != NULL)?(*root)->lchild:(*root)->rchild;
				free(p->data);
				free(p);

				success = 1;
				shorter = 1;
			}
		}//if compare
		else if(ret < 0)
		{
			success = AVLDelete(&((*root)->lchild), data, compare);
			if(shorter == 1)
			{
				switch((*root)->bf)
				{
				case LH:
					(*root)->bf = EH;
					shorter = 0;
					break;
				case EH:
					(*root)->bf = RH;
					break;
				case RH:
					RightBalanceD(root);
					break;
				}//switch
			}//if
		}//else if
		else if(ret > 0)
		{
			success = AVLDelete(&((*root)->rchild), data, compare);
			if(shorter == 1)
			{
				switch((*root)->bf)
				{
				case LH:
					LeftBalanceD(root);
					break;
				case EH:
					(*root)->bf = LH;
					break;
				case RH:
					(*root)->bf = EH;
					shorter = 0;
					break;
				}//switch
			}//if
		}//else if
	}//if root
	return success;
}
/*
output:
return 1:success
return 0:already exist
return -1:unexpected err
input: 
root:這棵平衡二叉樹的根節點;
data:欲插入的數據指針;
len:插入數據的大小;
compare:插入數據類型的比較函數;
*/
int taller= 0;
int  AVLInsert(AVLTree *root, void *data,int len, COMPARE_FUNC compare)
{
	int ret;
	if(NULL == (*root))
	{
		(*root) = (AVLTree)malloc(sizeof(AVLNode));

		if(NULL == (*root))
			return -1;
		(*root)->data = (void *)(char *)malloc(len);
		if(NULL == (*root)->data)
			return -1;
		memcpy((*root)->data, data, len);
		(*root)->lchild = NULL;
		(*root)->rchild = NULL;
		(*root)->bf = EH;
		taller = 1;
		return 1;
	}
	//the tree is not empty
	ret = compare(data, (*root)->data);
	//already exist
	if(0 == ret)
		return 0;
	else if(ret > 0)
	{
		ret = AVLInsert(&((*root)->rchild), data, len, compare);

		if(-1 == ret)
			return -1;
		else if( 0 == ret)
			return 0;
		if(taller != 0)
		{
			switch((*root)->bf)
			{
			case LH:
				(*root)->bf = EH;
				taller = 0;
				break;
			case  EH:
				(*root)->bf = RH;
				taller = 1;
				break;
			case RH:
				RightBalance(root);
				taller = 0;
				break;
			default:
				break;
			}
		}
	}
	else
	{
		ret = AVLInsert(&((*root)->lchild), data, len, compare);

		if(-1 == ret)
			return -1;
		else if( 0 == ret)
			return 0;
		if(taller != 0)
		{
			switch((*root)->bf)
			{
			case RH:
				(*root)->bf = EH;
				taller = 0;
				break;
			case EH:
				(*root)->bf = LH;
				taller = 1;
				break;
			case LH:
				LeftBalance(root);
				taller = 0;
				break;
			default:
				break;
			}
		}
	}
	return 1;
}
/*
 *free the tree
*/
void FreeTree(AVLTree *root)
{
	if(NULL != *root)
	{
		FreeTree(&((*root)->lchild));
		FreeTree(&((*root)->rchild));
		free((*root)->data);
		free(*root);
		*root = NULL;
	}
}
/*
search for the data in the avltree
input:
		root: root of the searching tree
		data:data to search
		compare:compare func for data
output:
		NULL:not find
		!NULL: find the result
*/
AVLNode *SearchAVLNode(AVLTree root, void *data, COMPARE_FUNC compare)
{
	int ret;

	if(NULL != root)
	{
		ret = compare(root->data, data);
		if(0 == ret)
			return root;
		else if(ret > 0)
			return SearchAVLNode(root->lchild, data, compare);
		else
			return SearchAVLNode(root->rchild, data, compare);
	}
	return NULL;
}
void in_order_tranverse(AVLTree root, int type)
{
	if(root)
	{
		in_order_tranverse(root->lchild, type);
		if(1 == type)//string
			printf("%s  %d\n",  (char *)(root->data), root->bf);
		else if(2 == type)
			printf("%d  %d\n",  *(int *)(root->data), root->bf);
		in_order_tranverse(root->rchild, type);
	}
}
void avltree_test()
{
	AVLTree string_root = NULL;
	AVLTree int_root = NULL;
	char *str[] = {"file", "edit", "view", "qt", "project", "build", "debug", "tools","window", "community", "help"};
	int num[]={34,24,67, 1, 56, 83, 27, 98};
	int  i;

	for(i = 0; i < sizeof(str)/sizeof(char *); i++)
		AVLInsert(&string_root, (void *)str[i], strlen(str[i]) +1, compare_string);
	for(i= 0; i< sizeof(num)/sizeof(int *); i++)
		AVLInsert(&int_root, (void *)(num + i), sizeof(int), compare_int);

	AVLDelete(&string_root, "qt", compare_string);

	in_order_tranverse(string_root, 1);
	in_order_tranverse(int_root, 2);
	if(SearchAVLNode(string_root, "project", compare_string))
		printf("Find project\n");
	else
		printf("Not find project\n");
	
	if(SearchAVLNode(string_root, "home", compare_string))
		printf("Find home\n");
	else
		printf("Not find home\n");

	if(SearchAVLNode(int_root, num + 3, compare_string))
		printf("Find %d\n", *(num + 3));
	else
		printf("Not find %d\n", *(num + 3));


	//FreeTree(&string_root);
	FreeTree(&int_root);
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章