平衡二叉树(AVL)的前提它得是有序二叉树,它的左右子树的高度差不超过1,而且它的所有子树也满足这个条件。那平衡树到底有什么意义呢,一切为效率服务:如果一个有序二叉树呈现接近单支状的链表,那么它的查找效率接近链表,因此只有达到平衡时它的查找效率最高。也可以理解为把有序的二叉树调整成一棵平衡树,所以核心就是调整的过程。
同样用链式结构表示,先构成数据项:
typedef struct TreeNode
{
int data;
struct TreeNode *left;
struct TreeNode *right;
}TreeNode;
下面我们要对现有数据项结构的树进行操作,包括了调整平衡等相关操作:
创建结点
//创建结点
TreeNode *create_node(int data)
{
TreeNode *node=malloc(sizeof(TreeNode));
node->data=data;
node->left=NULL;
node->right=NULL;
return node;
}
求高度
//求高度
int high_tree(TreeNode *root)
{
if(NULL==root) return 0;
int lh=high_tree(root->left);
int rh=high_tree(root->right);
return lh>rh?lh+1:rh+1;
}
检查左右子树是否平衡
//检查左右子树是否平衡
int is_balance(TreeNode *root)
{
return high_tree(root->left)-high_tree(root->right);
}
右旋转
//右旋转
TreeNode *right_rotate(TreeNode *x)
{
TreeNode *y=x->left;
TreeNode *t2=y->right;
y->right=x;
x->left=t2;
return y;
}
左旋转
//左旋转
TreeNode *left_rotate(TreeNode *x)
{
TreeNode *y=x->right;
TreeNode *t2=y->left;
y->left=x;
x->right=t2;
return y;
}
自动平衡
//自动平衡
TreeNode *auto_balance(TreeNode *x)
{
if(NULL==x) return NULL;
int lh=high_tree(x->left);
int rh=high_tree(x->right);
if(lh-rh > 1)
{
if(is_balance(x->left)>=0)
{
//右旋转
x=right_rotate(x);
}
else
{
//左旋转
x->left=left_rotate(x->left);
//右旋转
x=right_rotate(x);
}
}
if(rh-lh > 1)
{
if(is_balance(x->right)<=0)
{
x=left_rotate(x);
}
else
{
x->right=right_rotate(x->right);
x=left_rotate(x);
}
}
return x;
}
插入
//插入
TreeNode *insert_tree(TreeNode *root,int data)
{
if(NULL==root) return create_node(data);
if(data<root->data) root->left=insert_tree(root->left,data);
else root->right=insert_tree(root->right,data);
root=auto_balance(root);
return root;
}
前序遍历
//前序遍历
void preorder(TreeNode *root)
{
if(NULL==root) return;
printf("%d ",root->data);
preorder(root->left);
preorder(root->right);
}
中序遍历
//中序遍历
void midorder(TreeNode *root)
{
if(NULL==root) return;
midorder(root->left);
printf("%d ",root->data);
midorder(root->right);
}
删除
//删除
/*1、待删除的结点是叶子结点直接删除
2、待删除的结点左或右子树为空则使用非空子结点替换
3、待删除的结点左右子树非空,则根据左右子树的高度选择左边最大子结点或右边最小子结点进行替换*/
TreeNode *min_tree(TreeNode *root)
{
TreeNode *min=root;
while(min->left) min=min->left;
return min;
}
TreeNode *max_tree(TreeNode *root)
{
TreeNode *max=root;
while(max->right) max=max->right;
return max;
}
TreeNode *del_tree(TreeNode *root,int data)
{
if(NULL==root) return NULL;
if(data==root->data)
{
//左右子树为空
if(NULL==root->left && NULL==root->right)
{
free(root);
root=NULL;
return NULL;
}
//左子树为空
if(NULL==root->left)
{
TreeNode *temp=root->right;
free(root);
return temp;
}
//右子树为空
if(NULL==root->right)
{
TreeNode *temp=root->left;
free(root);
return temp;
}
//左右子树都不为空
int lh=high_tree(root->left);
int rh=high_tree(root->right);
if(lh>=rh)
{
TreeNode *node=max_tree(root->left);
root->data=node->data;
root->left=del_tree(root->left,root->data);
}
else
{
TreeNode *node=min_tree(root->right);
root->data=node->data;
root->right=del_tree(root->right,root->data);
}
return root;
}
if(data < root->data)
root->left=del_tree(root->left,data);
else
root->right=del_tree(root->right,data);
root=auto_balance(root);
return root;
}
大概就是这么些操作,测试:
int main(int argc,const char* argv[])
{
TreeNode *root=NULL;
for(int i=0;i<10;i++)
{
int data=rand()%100;
root=insert_tree(root,data);
}
//preorder(root);
printf("\n");
midorder(root);
printf("\n");
del_tree(root,92);
midorder(root);
return 0;
}
over