【AVL】平衡二叉树

主要是对于四种状态的旋转使其重新平衡,当使用平衡二叉树作为hash的存储结构时,bucket数量对性能的影响很大,bucket数量越多,树的深度越小,写入越快,查找也越快。

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <pthread.h>


#define G 1000000000


typedef struct tagNode {
	long value;

	struct tagNode *lnode;

	struct tagNode *rnode;

	struct tagNode *parent;
}Node_t;


void AVL( Node_t *node );


/* 二叉搜索树 */
int insert_bst( Node_t **node, int val )

{
	Node_t *root = *node;

	Node_t *newNode = (Node_t *) malloc( sizeof(Node_t) );

	if ( newNode == NULL )
	{
		fprintf( stderr, "memory alloc failed\n" );

		return(-1);
	}
	newNode->value = val;

	newNode->lnode = NULL;

	newNode->rnode = NULL;

	if ( root == NULL )
	{
		newNode->parent = NULL;

		*node = newNode;

		return(0);
	} else {
		Node_t *curr = root;

		for (;; )
		{
			if ( val <= curr->value )
			{
				if ( curr->lnode == NULL )
				{
					newNode->parent = curr;

					curr->lnode = newNode;

					AVL( newNode );
					return(0);
				}
				curr = curr->lnode;
			} else {
				if ( curr->rnode == NULL )
				{
					newNode->parent = curr;

					curr->rnode = newNode;

					AVL( newNode );
					return(0);
				}
				curr = curr->rnode;
			}
		}
	}
}


int get_tree_height( Node_t *root )

{
	int deep = 0;

	if ( root == NULL )
	{
		return(deep);
	}
	int ldeep = 0;

	int rdeep = 0;

	++deep;
	if ( root->lnode != NULL )
	{
		ldeep = get_tree_height( root->lnode );
	}
	if ( root->rnode != NULL )
	{
		rdeep = get_tree_height( root->rnode );
	}
	deep += ldeep > rdeep ? ldeep : rdeep;

	return(deep);
}


/* 左子树顺时针右旋 */
void LL_Rotate( Node_t *p )

{
	Node_t *lchild = p->lnode;

	int r_value = p->value;

	p->value = lchild->value;

	p->lnode = lchild->lnode;

	lchild->lnode->parent = p;

	lchild->value = r_value;

	lchild->lnode = lchild->rnode;

	lchild->rnode = p->rnode;

	p->rnode = lchild;
}


/* 右子树逆时针左旋 */
void RR_Rotate( Node_t *p )

{
	Node_t *rchild = p->rnode;

	int l_value = p->value;

	p->rnode = rchild->rnode;

	p->rnode->parent = p;

	p->value = rchild->value;

	rchild->value = l_value;

	rchild->rnode = rchild->lnode;

	rchild->lnode = p->lnode;

	p->lnode = rchild;
}


/* 左子树逆时针左旋 */
void LR_Rotate( Node_t *p )

{
	Node_t *lchild = p->lnode;

	Node_t *lrchild = lchild->rnode;

	lchild->rnode = lrchild->lnode;

	if ( lrchild->lnode != NULL )
	{
		lrchild->lnode->parent = lchild;
	}
	lchild->parent = lrchild;

	lrchild->parent = p;

	p->lnode = lrchild;

	lrchild->lnode = lchild;
}


/* 右子树顺时针右旋 */
void RL_Rotate( Node_t *p )

{
	Node_t *rchild = p->rnode;

	Node_t *rlchild = rchild->lnode;

	p->rnode = rlchild;

	rchild->parent = rlchild;

	rchild->lnode = rlchild->rnode;

	rlchild->parent = p;

	if ( rlchild->rnode != NULL )
	{
		rlchild->rnode->parent = rchild;
	}
	rlchild->rnode = rchild;
}


/*
 * 平衡二叉树 (对离插入节点最近且平衡因子绝对值大于1对节点进行重新平衡)
 * 自底向上查找平衡因子大于1的节点
 */
void AVL( Node_t *root )

{
	while ( root != NULL )
	{
		int ldeep = get_tree_height( root->lnode );

		int rdeep = get_tree_height( root->rnode );

		printf( "ldeep: %d, rdeep: %d\n", ldeep, rdeep );


		if ( (ldeep - rdeep) > 1 )
		{
			Node_t *lchild = root->lnode;

			if ( get_tree_height( lchild->lnode ) > get_tree_height( lchild->rnode ) )
			{
/* 顺时针右旋 */
				LL_Rotate( root );
			} else {
/* 逆时针左旋 */
				LR_Rotate( root );
/* 顺时针右旋 */
				LL_Rotate( root );
			}
			return;
		}


		if ( (rdeep - ldeep) > 1 )
		{
			Node_t *rchild = root->rnode;

			if ( get_tree_height( rchild->rnode ) > get_tree_height( rchild->lnode ) )
			{
/* 逆时针左旋 */
				RR_Rotate( root );
			} else {
/* 顺时针右旋 */
				RL_Rotate( root );
/* 逆时针左旋 */
				RR_Rotate( root );
			}
			return;
		}
		root = root->parent;
	}
}


void first_order_traver( Node_t *root )

{
	if ( root == NULL )
	{
		return;
	}
	printf( "%d ", root->value );

	first_order_traver( root->lnode );
	first_order_traver( root->rnode );
}


void inOrderTraverse( Node_t *root )

{
	if ( root == NULL )
	{
		return;
	}
	inOrderTraverse( root->lnode );
	printf( "%d ", root->value );

	inOrderTraverse( root->rnode );
}


Node_t* bi_search( Node_t *root, int val )

{
	while ( root != NULL )
	{
		if ( root->value == val )
		{
			return(root);
		} else if ( val > root->value )
		{
			root = root->rnode;
		} else {
			root = root->lnode;
		}
	}
	return(NULL);
}


int main( void )

{
	Node_t *root = NULL;

	int i = 0;

	long rand_num;

	for (; i < 100000; i++ )
	{
		rand_num = random() % 10000;

/* printf("insert %ld\n", rand_num); */
		insert_bst( &root, rand_num );

/*
 * printf("先序遍历 :");
 * first_order_traver(root);
 * printf("\n中序遍历 :");
 * inOrderTraverse(root);
 * printf("\n");
 */
	}
	int deep = get_tree_height( root );

	printf( "insert %d items, tree deep %d\n", i, deep );


/*
 * first_order_traver(root);
 * printf("\n");
 * inOrderTraverse(root);
 * printf("\n");
 */
	struct timespec start, end;

	clock_gettime( CLOCK_REALTIME, &start );
	Node_t *result = bi_search( root, 112 );

	clock_gettime( CLOCK_REALTIME, &end );
	long cost = (end.tv_sec * G + end.tv_nsec) - (start.tv_sec * G + start.tv_nsec);


	if ( result != NULL )
	{
		printf( "result %x, cost time %ld ns\n", result, cost );
	} else {
		printf( "not find the result!\n" );
	}
	return(0);
}


AVL 调 整平衡 自顶 向 的方 式 和自底 向 的方 式总 体来 自底 向 的方 式 性 能要 好 一 些
#ifdef UP_TO_DOWN

int cnt = 0;

/*
 * 平衡二叉树 (对离插入节点最近且平衡因子绝对值大于1对节点进行重新平衡)
 * 自顶向下
 */
void AVL( Node_t *root )

{
	++cnt;
	if ( cnt % 10000 == 0 )
	{
		printf( "avl %d\n", cnt );
	}
	while ( root != NULL )
	{
		int ldeep = get_tree_height( root->lnode );

		int rdeep = get_tree_height( root->rnode );

/* printf("ldeep: %d, rdeep: %d\n", ldeep, rdeep); */
		if ( (ldeep - rdeep) > 1 )
		{
			Node_t *lchild = root->lnode;

			ldeep = get_tree_height( lchild->lnode );

			rdeep = get_tree_height( lchild->rnode );

			if ( (ldeep - rdeep) > 1 || (rdeep - ldeep) > 1 )
			{
				root = lchild;
				continue;
			}
			if ( get_tree_height( lchild->lnode ) > get_tree_height( lchild->rnode ) )
			{
/* 顺时针右旋 */
				LL_Rotate( root );
			} else {
/* 逆时针左旋 */
				LR_Rotate( root );
/* 顺时针右旋 */
				LL_Rotate( root );
			}
			return;
		}
		if ( (rdeep - ldeep) > 1 )
		{
			Node_t *rchild = root->rnode;

			ldeep = get_tree_height( rchild->lnode );

			rdeep = get_tree_height( rchild->rnode );

			if ( (ldeep - rdeep) > 1 || (rdeep - ldeep) > 1 )
			{
				root = rchild;
				continue;
			}
			if ( get_tree_height( rchild->rnode ) > get_tree_height( rchild->lnode ) )
			{
/* 逆时针左旋 */
				RR_Rotate( root );
			} else {
/* 顺时针右旋 */
				RL_Rotate( root );
/* 逆时针左旋 */
				RR_Rotate( root );
			}
			return;
		}
		return;
	}
}


#else
/*
 * int cnt = 0;
 * 平衡二叉树 (对离插入节点最近且平衡因子绝对值大于1对节点进行重新平衡)
 * 自底向上
 */
void AVL( Node_t *root )

{
/*
 * ++cnt;
 * if (cnt % 10000 == 0) {
 * printf("avl %d\n", cnt);
 * }
 */
/**自底向上查找平衡因子大于1的节点**/
	while ( root != NULL )
	{
		int ldeep = get_tree_height( root->lnode );

		int rdeep = get_tree_height( root->rnode );

/* printf("ldeep: %d, rdeep: %d\n", ldeep, rdeep); */


		if ( (ldeep - rdeep) > 1 )
		{
			Node_t *lchild = root->lnode;

			if ( get_tree_height( lchild->lnode ) > get_tree_height( lchild->rnode ) )
			{
/* 顺时针右旋 */
				LL_Rotate( root );
			} else {
/* 逆时针左旋 */
				LR_Rotate( root );
/* 顺时针右旋 */
				LL_Rotate( root );
			}
			return;
		}


		if ( (rdeep - ldeep) > 1 )
		{
			Node_t *rchild = root->rnode;

			if ( get_tree_height( rchild->rnode ) > get_tree_height( rchild->lnode ) )
			{
/* 逆时针左旋 */
				RR_Rotate( root );
			} else {
/* 顺时针右旋 */
				RL_Rotate( root );
/* 逆时针左旋 */
				RR_Rotate( root );
			}
			return;
		}
		root = root->parent;
	}
}


#endif

通 过平衡二叉 树 实现hash存储
typedef struct tagbucket {
	Node_t *bucket;

	int num;
} bucket_t;


typedef struct taghash {
	bucket_t buckets[BUCKET_NUM];

	int bucket_num;
} node_hash_t;


int main( void )

{
	Node_t *root = NULL;

	int i = 0;

	long rand_num;

	node_hash_t hash;

	memset( hash.buckets, 0, sizeof(hash.buckets) );

	hash.bucket_num = BUCKET_NUM;

	for (; i < 1000000; i++ )
	{
		rand_num = i;

/* printf("insert %ld\n", rand_num); */
		int bucket_idx = rand_num % hash.bucket_num;

		insert_bst( &hash.buckets[bucket_idx].bucket, rand_num );

		hash.buckets[bucket_idx].num++;
/*
 * printf("先序遍历 :");
 * first_order_traver(root);
 * printf("\n中序遍历 :");
 * inOrderTraverse(root);
 * printf("\n");
 */
	}
	for ( int i = 0; i < hash.bucket_num; i++ )

	{
		int deep = get_tree_height( hash.buckets[i].bucket );

		printf( "bucket %d insert %d ,tree deep %d\n", i, hash.buckets[i].num, deep );
	}


/*
 * first_order_traver(root);
 * printf("\n");
 * inOrderTraverse(root);
 * printf("\n");
 */
	long total_time = 0;

	int loop = 10000;

	int hit_num = 0;

	long max_time = 0, min_time = G;

	for ( int i = 0; i < loop; i++ )
	{
		struct timespec start, end;

		clock_gettime( CLOCK_REALTIME, &start );
		rand_num = random() % 100000;

		int bucket_idx = rand_num % hash.bucket_num;

		Node_t *result = bi_search( hash.buckets[bucket_idx].bucket, rand_num );

		clock_gettime( CLOCK_REALTIME, &end );
		long cost = (end.tv_sec * G + end.tv_nsec) - (start.tv_sec * G + start.tv_nsec);

		max_time = max_time < cost ? cost : max_time;

		min_time = min_time > cost ? cost : min_time;

		total_time += cost;

		if ( result != NULL )
		{
			hit_num++;
/* printf("result %x, cost time %ld ns\n", result, cost); */
		} else {
/* printf("cost time %ld ns, not find the result!\n", cost); */
		}
	}
	long avg_time = total_time / loop;

	printf( "average cost time %ld, max cost time %ld, min cost time %ld, total search %d, hits %d\n",
		avg_time, max_time, min_time, loop, hit_num );


	return(0);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值