测试上一节二叉查找树在极端情况下的例子:
为了解决这个问题,就需要通过增加一些属性和变化,将二叉查找树转为(在创建二叉树时候进行旋转让二叉树再次平衡)二叉平衡树。
AVL树(由G.M.Adelson-Velsky和Evgenii Landis发明,AVL命名是使用两个人的名字缩写组成)是最早的自平衡二叉搜索树,AVL树中,任一结点对应的两棵子树的最大高度差不超过1 。
在二叉树中满二叉树
(除叶子结点外的所有结点均有两个子结点。节点数达到最大值。所有叶子结点必须在同一层上。)和完全二叉树
(二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边)天生就是一棵平衡二叉树
。
注意: 平衡二叉树不一定是完全二叉树。
平衡二叉树:对于任意一个结点左右子树高度差不能超过1。
所以AVL可以理解是在二分查找树的基础上兼顾了其平衡性。AVL又名平衡二叉查找树简称为平衡二叉树。
二. 平衡因子
先回顾一下二叉树结点的高度和深度:
-
深度:深度是从根结点开始算,表示从根到某一个结点唯一的路径的长(该路径长边的条数)。
-
高度:表示某一个结点到叶子结点最长路径的长。
下面看一个例子:
接着看一个什么是平衡因子 :某个结点的左子树的高度减去右子树的高度得到的差值。
下图是一个非平衡二叉树
和平衡二叉树
平衡因子的展示:
三. AVL初始化
3.1. 结点定义
定义AVL树结点:
// TreeNode AVL结点定义
type TreeNode struct {
data int // 结点数据
height int // 结点高度
left *TreeNode // 左孩子
right *TreeNode // 右孩子
}
// NewTreeNode 构建一个新结点
func NewTreeNode(data int) *TreeNode {
return &TreeNode{
height: 0,
left: nil,
right: nil,
data: data,
}
}
复制代码
可以在二叉查找树的基础上进行修改,这里重点实现插入和删除的操作,其他一些基本上都和二叉树操作一样。
type AVLTree struct {
root *TreeNode
}
// Insert 插入
func (a *AVLTree) Insert(data int) {
// TODO
}
// Delete 删除
func (a *AVLTree) Delete(data int) {
// TODO
}
复制代码
下面还需要增加一些辅助函数,帮助后面插入和删除的操作。
3.2. 结点高度
在结点中包含了height
的