数据结构之AVL树
文章目录
前言
数据结构对于每一个编程人员来说都是十分重要的,而其中的二叉树就是最鲜明的代表。让我们来一起了解其中特别有魅力的AVL树吧。
提示:
一、AVL树是什么?
1.1AVL树的概念
由百度百科可知其是一颗二叉平衡搜索树。其中有三点重要信息:
1、二叉树:(节点的度最多为2的树,也就是最多只能有两个孩子的树为二叉树)
2、平衡树:(就是左右子树的高度差不能超过一的树为平衡树)。
3、搜索树:(就是按照中序或者后续的方法去遍历这棵树的时候他是有序的为搜索树)
然后它大概就长下面这样。
二、AVL树的实现
1.AVL树的调整
1.1AVL树的底层树调整
AVL树不满足平衡条件时肯定是因为向其某个叶子节点中添加元素导致的,所以其处理的情况有一下三种。
1.出现左右单支的情况,肯定不满足,平衡因子等于2.和-2.
针对于左单支需要右旋,而右单支需要左旋
:
左单支:(对于本例)将节点中值为3的节点提上去作为父节点,将值为4的节点拿下来作为3的右孩子就行了。
右单支:(对于本例)将节点中值为2的节点提上去作为父节点,将值为1的节点拿下来作为左孩子就完成了。
2.当出现往左孩子的右孩子添加元素时导致的平衡因子发生改变不满足AVL树的规则
需要先以左孩子为根的树进行一次左单旋,(也就是将subL向下放,将subLR向上提),使其成为左单支的情况,然后按照左单支的情况进行一次右单旋。
3、当出现往右孩子的左孩子添加元素时导致的平衡因子发生改变不满足AVL树的规则
需要先以右孩子为根的树进行一次右单旋,(也就是将5向下放,将4向上提),使其成为右单支的情况,然后按照右单支的情况进行一次左单旋。
1.2AVL树的往上层调整
向上层调整的时候就需要考虑到该节点的叔叔节点。两种情况。
1、该节点为父亲节点的左孩子,如果左孩子的右孩子不空,则将右孩子的父节点更改。
2、该节点为父亲节点的右孩子,如果右孩子的左孩子不空,则将右孩子的父节点更改。
1.3AVL树的调整总结
当无论处理以上哪一种情况之后就会将平衡因子处理为0,因为在添加时上层已经是AVL树了,你填加的时候只是破坏了某个节点及其以后的树的规则,故不再需要向上更新。
2.AVL树的C++实现
AVL树的节点结构,因为它需要调整树的结构及节点的位置,所以需要孩子双亲表示法去表示,并且需要在结构体中给出构造函数,在C++中的结构体的默认属性是共有的。
template<class T>
struct AVLTreeNode {
//定义节点类型,用孩子双亲表示法来表示
AVLTreeNode<T>* left;
AVLTreeNode<T>* right;
AVLTreeNode<T>* parent;
T data; //数据
int bf; //平衡因子
AVLTreeNode(const T& x) //构造函数
:left(nullptr)
,right(nullptr)
,parent(nullptr)
,data(x)
,bf(0)
{
}
};
AVL树的插入实现
template<class T>
class AVLTree {
typedef AVLTreeNode<T> Node;
public:
//构造和析构函数
AVLTree():root(nullptr){
}
~AVLTree() {
DestroyTree(root); }
//AVLTree的插入
bool insert(const T& val) {
if (root == nullptr) //没有节点时,为根节点直接插入
{
root =