平衡二叉树
简介
AVL树的名字来源于它的发明作者G.M. Adelson-Velsky 和 E.M. Landis。AVL树是最先发明的自平衡二叉查找树(Self-Balancing Binary Search Tree,简称平衡二叉树)。
平衡二叉树定义(AVL):它或者是一颗空树,或者具有以下性质的二叉排序树:它的左子树和右子树的深度之差(平衡因子)的绝对值不超过1,且它的左子树和右子树都是一颗平衡二叉树。
判断的必要条件
- 平衡二叉树一定是二叉搜索树
- 平衡二叉树的左右子树的高度差不超过1
题目实例
二叉树的平衡性:
利用二叉树遍历的思想,编写一个判断二叉树是否是一棵平衡二叉树的算法。
输入:第一行输入n,表示有n个数组元素,第二行输入二叉树的拓展前序遍历数组,空结点用0表示
输出:true或false
样例输入1:
11
50 45 46 0 0 0 65 0 70 0 0
样例输出1:false
样例输入2:
11
50 45 45 0 0 0 65 0 70 0 0
样例输出2:true
代码实现
#include<iostream>
using namespace std;
typedef struct node //二叉树结构定义
{
int data;
struct node* left, * right;
}BiNode,*BiTree;
void CreateTree(BiTree& root, int arr[],int n); //生成二叉树
void PreOrder(BiTree root); //判断是否为搜索二叉树
int height(BiTree root); //判断左右子树高度
int flag = 0; //用于标记左右子树的最大高度差
int flag1 = 0, flag2 = 0; //用于标记二叉树的左右节点是否符合搜索二叉树的定义
int i = 0; //用于标记生成二叉树途中数组元素的位置
int main()
{
int n, arr[1000];
cin >> n;
for (int i = 0; i < n; i++)
cin >> arr[i]; //获取数组元素
BiTree root = NULL, p = NULL;
CreateTree(root, arr, i); //先序序列数组转为二叉树
PreOrder(root); //先序遍历中判断是否符合搜索二叉树
if (flag1 == 0&&flag2==0) //二者均为0说明符合搜索二叉树
{
height(root); //判断任意节点左右子树高度差是否小于等于1,小于则是AVL
if (flag <= 1)
cout << "true";
else
cout << "false";
}
else
cout << "flase";
return 0;
}
void CreateTree(BiTree& root, int arr[],int n) //将数组转为二叉树
{
if (i >= n) //数组元素转化完毕,所有递归都开始退出
return;
if (arr[i] == 0)
{
i++;
return;
}
root = new BiNode;
root->left = root->right = NULL;
root->data = arr[i++];
CreateTree(root->left, arr,n); //录入左子树
CreateTree(root->right, arr,n); //录入右子树
}
//用先序遍历来判断是否符合搜索二叉树定义
//即左节点小于父节点,右节点大于父节点
void PreOrder(BiTree root)
{
if (root == NULL) //遇见空节点退出
return ;
if (root->left != NULL) //左节点不为空进进去判断与父节点大小关系
{
if (root->left->data > root->data) //如果左节点大于父节点,说明不符合搜索二叉树定义,因此将flag1标记为1
{ //表明不是AVL树
flag1 = 1;
}
}
if (root->right != NULL) //同理,判断右节点与父节点关系
{
if (root->right->data < root->data) //如果右节点小于父节点,违反搜索二叉树定义,flag2标记为1
{ //表明不是AVL树
flag2 = 1;
}
}
PreOrder(root->left); //递归判断左子树
PreOrder(root->right); //递归判断右子树
}
//随便取名了,用来求树高,同时判断节点的左右子树的高度差
int height(BiTree root)
{
if (root == NULL) //空结点的高度为0
{
return 0;
}
int h1 = height(root->left) + 1; //左子树高度加1即是从左子树往上数的本层高度
int h2 = height(root->right) + 1; //右子树高度加1即是右子树往上数的本层高度
/*
h1与h2之间差的绝对值即是左右子树的高度差,而flag=max{flag,左右子树高度差}
*/
if (h1 > h2)
{
flag = flag > h1 - h2 ? flag : h1 - h2;
}
else
{
flag = flag > h2 - h1 ? flag : h2 - h1;
}
return h1 > h2 ? h1 : h2; //左右子树高度+1后更大的才是本层的高度
}