1.概念
1.AVL树必须满足是一棵二叉查找(排序)树
2.任意节点左右子树高度差不能超过1
2.插入操作
插入操作有可能让树不满足第二条规则,那么必须旋转树。有四种旋转方式
1.单次左旋(左旋可以理解为旋转左边的孩子,右旋同理) ----> 在节点的左孩子左子树上插入,高度差 = 2
2.先右旋,再左旋 ----> 在节点的左孩子右子树上插入,高度差 = 2
3.单次右旋 ----> 在节点的右孩子右子树上插入,高度差 = -2
4.先左旋,再右旋 ----> 在节点的右孩子左子树上插入,高度差 = -2
记住,插入操作的结尾处,必须要更新当前节点的高度,方法为max(left->height,right->height)+1
以下附上自己实现的一个AVL树源码(remove操作还没有完成,不好意思)
avl_tree.h
#ifndef __AVL_TREE_H__
#define __AVL_TREE_H__
#include <malloc.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
typedef struct _unode
{
int id;
// char* name;
// char* pass;
}unode;
int isLess(const unode* lhs,const unode* rhs)
{
return lhs->id < rhs->id;
}
int isGreat(const unode* lhs,const unode* rhs)
{
return lhs->id > rhs->id;
}
int isEqual(const unode* lhs,const unode* rhs)
{
return lhs->id == rhs->id;
}
typedef struct _tnode
{
unode* data;
struct _tnode* left;
struct _tnode* right;
int height;
}tnode;
void singleRotateLeft(tnode** root);
void doubleRotateLeft(tnode** root);
void singleRotateRight(tnode** root);
void doubleRotateRight(tnode** root);
void singleRotateLeft(tnode** root)
{
tnode* k1 = (*root)->left;
(*root)->left = k1->right;
k1->right = *root;
(*root)->height = max(height((*root)->left),height((*root)->right)) + 1;
k1->height = max(height(k1->left),height(k1->right)) + 1;
*root = k1;
}
void doubleRotateLeft(tnode** root)
{
singleRotateRight(&(*root)->left);
singleRotateLeft(root);
}
void singleRotateRight(tnode** root)
{
tnode* k1 = (*root)->right;
(*root)->right = k1->left;
k1->left = *root;
(*root)->height = max(height((*root)->left),height((*root)->right)) + 1;
k1->height = max(height(k1->left),height(k1->right)) + 1;
*root = k1;
}
void doubleRotateRight(tnode** root)
{
singleRotateLeft(&(*root)->right);
singleRotateRight(root);
}
tnode* create_avl_tree(const unode* p)
{
//tnode* root = (tnode*)malloc(sizeof(tnode));
//root->data = p;
//root->left = root->right = NULL;
//root->height = 0;
//return root;
return NULL;
}
int height(const tnode* node)
{
if(node == NULL)
{
return -1;
}
return node->height;
}
void insert(tnode** root,tnode* data)
{
tnode* r = *root;
if( *root == NULL )
{
*root = data;
}
else if( isGreat( (*root)->data, data->data ) )
{
insert( &((*root)->left), data );
if(height((*root)->left) - height((*root)->right) == 2) // ready to rotate
{
if(isLess(data->data,(*root)->left->data))
{
printf("singleRotateLeft ==> %d\n",data->data->id);
singleRotateLeft(&(*root));
}
else
{
printf("doubleRotateLeft ==> %d\n",data->data->id);
doubleRotateLeft(&(*root));
}
}
}
else if( isLess( (*root)->data, data->data ) )
{
insert( &((*root)->right), data );
if(height((*root)->left) - height((*root)->right) == -2) // ready to rotate
{
if(isGreat( data->data,(*root)->right->data))
{
printf("singleRotateRight ==> %d\n",data->data->id);
singleRotateRight(&(*root));
}
else
{
printf("doubleRotateRight ==> %d\n",data->data->id);
doubleRotateRight(&(*root));
}
}
}
else if( isEqual( (*root)->data, data->data ) )
{
assert(0);
}
(*root)->height = max(height((*root)->left),height((*root)->right)) + 1;
}
tnode* find(tnode* root,const unode* id)
{
if(root != NULL)
{
if(isEqual(root->data, id))
{
return root;
}
else if(isLess(id, root->data))
{
return find(root->left,id);
}
else if(isGreat(id, root->data))
{
return find(root->right,id);
}
}
return NULL;
}
void remove(tnode** root,const unode* id)
{
tnode* p = NULL;
tnode* q = *root;
while(q != NULL)
{
if(isEqual(q->data, id))
{
break;
}
else if(isLess(id, q->data))
{
p = q;
q = q->left;
}
else if(isGreat(id, q->data))
{
p = q;
q = q->right;
}
}
if(q->left == NULL && q->right == NULL) // 无子节点
{
if(p != NULL) // 删除的节点非根节点
{
if(isLess(q->data,p->data))
{
p->left = NULL;
}
else
{
p->right = NULL;
}
free(q);
}
else // 删除的节点为根节点
{
*root = NULL;
free(q);
}
}
else if(q->left == NULL && q->right != NULL) // 只有右儿子
{
if(p != NULL) // 删除的节点非根节点
{
if(isLess(q->data,p->data))
{
p->left = q->right;
}
else
{
p->right = q->right;
}
free(q);
}
else
{
*root = q->right;
free(q);
}
}
else if(q->left != NULL && q->right == NULL) // 只有左儿子
{
if(p != NULL) // 删除的节点非根节点
{
if(isLess(q->data,p->data))
{
p->left = q->left;
}
else
{
p->right = q->left;
}
free(q);
}
else
{
*root = q->left;
free(q);
}
}
else if(q->left != NULL && q->right != NULL)
{
// 查找右子树中最小的节点,并进行替换
tnode* minNode = q->right;
unode* tmp = (unode*)malloc(sizeof(unode));
while(minNode->left != NULL)
{
minNode = minNode->left;
}
memcpy(tmp,minNode->data,sizeof(unode));
// 删除那个最小的节点
remove(&q,minNode->data);
q->data = tmp;
}
}
void printTreeBefore(const tnode* root,int layer)
{
int t = layer;
if(root != NULL)
{
while(t-- > 0)
{
printf(" ");
}
printf("--> %d at %d\n",root->data->id,root->height);
printTreeBefore(root->left,layer + 1);
printTreeBefore(root->right,layer + 1);
}
}
void printTreeMiddle(const tnode* root,int layer)
{
int t = layer;
if(root != NULL)
{
printTreeMiddle(root->left,layer + 1);
while(t-- > 0)
{
printf(" ");
}
printf("--> %d at %d\n",root->data->id,root->height);
printTreeMiddle(root->right,layer + 1);
}
}
void printTreeAfter(const tnode* root,int layer)
{
int t = layer;
if(root != NULL)
{
printTreeAfter(root->left,layer + 1);
printTreeAfter(root->right,layer + 1);
while(t-- > 0)
{
printf(" ");
}
printf("--> %d at %d\n",root->data->id,root->height);
}
}
#endif
测试文件
#include "avltree.h"
int main()
{
int n = 0;
int i = 0;
//int dlist[] = {144,20,235,83,64,253,246,277,25,296};
//int dlist[] = {10,12,14,16};
//int dlist[] = {10,8,6,4};
int dlist[] = {50,20,30,25,35,32};
tnode* root;
tnode* p1 = NULL;
unode* d = (unode*)malloc(sizeof(unode));
d->id = 30;
root = create_avl_tree(d);
srand(time(0));
for(;i < _countof(dlist);i++)
{
tnode* p = (tnode*)malloc(sizeof(tnode));
p->data = (unode*)malloc(sizeof(unode));
//p->data->id = (int)(rand() / 100.0);
p->data->id = dlist[i];
p->left = p->right = NULL;
insert(&root,p);
printf("--> %d\n",p->data->id);
}
// p1 = find(root,54);
// p1 = find(root,246);
// p1 = find(root,83);
// p1 = find(root,235);
printf("-------------------\n");
printTreeBefore(root,0);
remove(&root,d);
printf("-------------------\n");
printTreeBefore(root,0);
printf("-------------------\n");
printTreeMiddle(root,0);
printf("-------------------\n");
printTreeAfter(root,0);
n = 11100;
}