平衡二叉树(AVL)
原创
©著作权归作者所有:来自51CTO博客作者prinsenten的原创作品,请联系作者获取转载授权,否则将追究法律责任
什么是平衡二叉树?
是一个合理的二叉排序树,比如 1 2 3 4 5的二叉树 可能全部是右子树,如果要查找5就需要5次
但是平衡二叉树的左右子树高度差不超过1,会将值分别放在左右两侧
关键在于如何构建一棵平衡二叉树?
1.本质上和构建二叉排序树一样
2.在构建二叉排序树的过程中,如果发现树不符合特性,就需要调整
有以下四种情况 LL RR LR RL
那么如何判断是需要调整的类型呢?
1.找到失衡树的根节点 root
2.找到导致树失衡的节点 node,观察node在root的哪一侧
3.判读node在root孩子的哪一侧
RR:取中间节点,使其父结点变成左孩子,如果有左孩子的话,那么这个左孩子连接到父节点的右孩子上
root->rchild=child->lchild
child->lchild=root
LL:取中间节点,使其父结点变成右孩子,如果有右孩子的话,那么这个右孩子连接到父节点的左孩子上(同理)
root->lchlid=node->rchlid
node->rchild=rott
LR:取最后一个节点作为父节点,将他的父亲作为自己的左孩子,将他的父亲的父亲作为自己的右孩子,如果他有左孩子或者右孩子的话,它原先的左孩子,连接到父亲的右孩子上,它现在的右孩子,连接到父亲的父亲的左孩子上
RL:取最后一个节点作为父节点,将他原先的父亲作为自己的右孩子,将父亲的父亲作为自己的左孩子,如果自己有左孩子,将原先的左孩子连接到父亲的父亲的右孩子上,自己原先的右孩子连接到父亲的左孩子上。
对于LR的具体操作 其实主要为先进行RR后,进行LL操作
#include<stdio.h>
#include<stdlib.h>
typedef struct TreeNode
{
int data;
int height;//记录高度
struct TreeNode* lchild, * rchild;
}TreeNode;
int getHeight(TreeNode* node)
{
return node ? node->height: 0;
}
int Max(int a,int b)
{
return a > b ? a : b;
}
void rrRotation(TreeNode* node, TreeNode** root)
{
TreeNode* temp = node->rchild;//node为根节点 temp即为右孩子
node->rchild = temp->lchild;//父亲的右孩子等于 temp的左孩子
temp->lchild = node;//temp的左孩子等于父节点
node->height = Max(getHeight(node->lchild), getHeight(node->rchild)) + 1;
temp->height = Max(getHeight(temp->lchild), getHeight(temp->rchild)) + 1;
*root = temp;//根节点变化
}
void llRotation(TreeNode* node, TreeNode** root)
{
TreeNode* temp = node->lchild;
node->lchild = temp->rchild;
temp->rchild = node;
node->height = Max(getHeight(node->lchild), getHeight(node->rchild)) + 1;
temp->height = Max(getHeight(temp->lchild), getHeight(temp->rchild)) + 1;
*root = temp;
}
void avlInsert(TreeNode** T, int data)
{
if (*T == NULL)
{
*T = (TreeNode*)malloc(sizeof(TreeNode));
(*T)->data = data;
(*T)->height = 0;
(*T)->lchild = NULL;
(*T)->rchild = NULL;
}
else if (data < (*T)->data)
{
avlInsert(&(*T)->lchild, data);
//拿到当前节点左右子树的高度
int lHeight = getHeight((*T)->lchild);
int rHeight = getHeight((*T)->rchild);
//判断高度差
if (lHeight - rHeight == 2)
{
if (data < (*T)->lchild->data)
{
//LL调整
llRotation(*T, T);
}
else
{
//LR调整
rrRotation((*T)->lchild, &(*T)->lchild);
llRotation(*T, T);
}
}
}
else if (data > (*T)->data)
{
avlInsert(&(*T)->rchild, data);
//拿到当前节点左右子树的高度
int lHeight = getHeight((*T)->lchild);
int rHeight = getHeight((*T)->rchild);
//判断高度差
if (rHeight - lHeight == 2)
{
if (data > (*T)->rchild->data)
{
//RR调整
rrRotation(*T, T);
}
else
{
//RL调整
llRotation((*T)->rchild, &(*T)->rchild);
rrRotation(*T, T);
}
}
}
(*T)->height = Max(getHeight((*T)->lchild), getHeight((*T)->rchild)) + 1;
}
void preOrder(TreeNode* T)
{
if (T)
{
printf("%d ", T->data);
preOrder(T->lchild);
preOrder(T->rchild);
}
}
int main()
{
TreeNode* T = NULL;
int nums[5] = { 1,2,3,4,5 };
for (int i = 0; i < 5; i++)
{
avlInsert(&T, nums[i]);
}
preOrder(T);
printf("\n");
return 0;
}