为什么要用到平衡二叉树:
我们都知道,普通的搜索树在良好的情况下,是一个类似于完全二叉树的树状结构,它所用到的时间复杂度为 O(logN),也就是高度次,但是难免有遇到极端场景,树状就退化成了单支树,这时的时间复杂度就变成了 O(N),严重影响了效率。
为了提升效率,让搜索树的时间复杂度达到 O(logN),我们需要使得搜索树达到高度平衡的状态,于是发明了 AVL树,从而达到近似平衡。
AVL树的性质:
AVL树有以下性质:
·左右子树都是AVL树
·左右子树的高度差(平衡因子)绝对值不超过1
什么是是左右子树高度差呢?就是一棵树的左子树和右子树,要不左子树比右子树多一层,要么少一层,如果新增的节点高度差绝对值超过 1,那么就得发生旋转,达到近似平衡。
如何控制平衡因子:
首先我们的AVL树中的每个节点都是一个结构体类型,每个结构体中包含了:
左,右节点指针、
父类节点的指针、
以及平衡因子(整型)。
AVL树的精髓就是控制每个节点的平衡因子,默认节点为0,因为每个新增的节点都是一个叶子节点,没有左右子树,当左子树新增一个节点时,父类的平衡因子 -1,当右子树新增节点时,父类的平衡因子 +1,如果父类的平衡因子为 -2 / 2 时,就要发生左旋和右旋,左、右旋又包含了左(右)单旋和右(左)双旋,用哪种主要看爷爷,也就是父亲的父亲节点。
记住,每个节点的平衡因子发生改变会影响父亲节点的平衡因子,所以要迭代更新到根节点。
右单旋:
触发条件 -- 父亲的平衡因子为 -2 ,子节点的平衡因子为 -1,让父亲节点发生右旋,子节点的右子树指向父亲,原来的右子树变成了父亲的左子树。随后随后爷爷的左子树指向子树,如果爷爷为空,那么子树就是根。
左右单旋:
触发条件 -- 父亲的平衡因子为 -2 ,子节点的平衡因子为 1,也就是新增节点在右子树,所以先让子节点发生左旋,变成单链,触发右单旋的条件,让父亲节点发生右旋,跟新平衡因子。
右单旋与左右单旋相反即可。
这样,搜索时所消耗的时间就是深度次 O(logN) ,在以亿为单位的数据面前,秩序要几十次即可,大大提高了效率。