数据结构课程设计之平衡二叉树算法实现。
什么是平衡二叉树?
是一种结构平衡的二叉搜索树,是一种每个节点的左右子树高度差都不超过1的二叉树。
由前苏联的数学家 Adelse-Velskil 和 Landis 在 1962 年提出的高度平衡的二叉树,根据科学家的英文名也称为 AVL 树。它具有如下几个性质:
- 可以是空树。
- 假如不是空树,任何一个结点的左子树与右子树都是平衡二叉树,并且高度之差的绝对值不超过 1。
举个例子,下图不是平衡二叉树,因为结点 60 的左子树高度为2,右子树高度为0,高度超过1。
什么是二叉搜索树?
它或者是一棵空树,或者是具有下列性质的 二叉树 : 若它的左子树不空,则左子树上所有结点的值均小于它的 根结点 的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为 二叉排序树 。. 二叉搜索树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势;所以应用十分广泛,例如在文件系统和数据库系统一般会采用这种数据结构进行高效率的排序与检索操作。
为什么要拥有平衡二叉树呢?
二叉搜索树一定程度上可以提高搜索效率,但是当原序列有序时,例如序列 A = {1,2,3,4,5,6},构造二叉搜索树如下图。依据此序列构造的二叉搜索树为右斜树,同时二叉树退化成单链表,搜索效率降低为 O(n)。
二叉搜索树的查找效率取决于树的高度,因此保持树的高度最小,即可保证树的查找效率。同样的序列 A,将其改为下图的方式存储,查找元素 6 时只需比较 3 次,查找效率提升一倍。
可以看出当节点数目一定,保持树的左右两端保持平衡,树的查找效率最高。
这种左右子树的高度相差不超过 1 的树为平衡二叉树。
平衡因子:
某结点的左子树和右子树的高度差即为该结点的平衡因子,平衡二叉树中不存在平衡因子大于 1 的节点。
如何构造平衡二叉树?
首先我们知道,平衡二叉树是一颗二叉树,我们二叉树结构具有左子树、右子树、值,而在平衡二叉树,由于我们需要检查它的平衡性,以及失衡调整操作,我们需要定义一个深度。下面代码块是平衡二叉树的定义。
//平衡二叉树的结构
typedef struct AVLNode{
int depth;//深度
struct AVLNode *left;//左孩子
struct AVLNode *right;//右孩子
struct AVLNode *parent;//父结点
ElenmentType value; //值
}AVLtree,Tree;
平衡二叉树的初始化:
//初始化
Tree* Init(ElenmentType value){
Tree* root=new Tree();
root->parent = NULL;
root->depth = 0;
root->left = root->right = NULL;
root->value=value;
return root;
}
平衡二叉树插入时的失衡和调整:
二叉树的基本操作有:插入、删除、遍历等。
对于平衡二叉树而言,插入和删除会导致二叉树的失衡。
下图是一棵平衡二叉树
在此平衡二叉树插入节点 99 ,树结构变为:
节点 66 的左子树高度为 1,右子树高度为 3,此时平衡因子为 -2,树失去平衡。
最小失衡子树:在新插入的结点向上查找,以第一个平衡因子的绝对值超过 1 的结点为根的子树称为最小不平衡子树。也就是说,一棵失衡的树,是有可能有多棵子树同时失衡的。而这个时候,我们只要调整最小的不平衡子树,就能够将不平衡的树调整为平衡的树。
平衡二叉树的失衡调整主要是通过旋转最小失衡子树来实现的。
根据旋转的方向有两种处理方式,左旋 与 右旋 。
旋转的目的就是减少高度,通过降低整棵树的高度来平衡。哪边的树高,就把那边的树