主要是对于四种状态的旋转使其重新平衡,当使用平衡二叉树作为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);
}