目录
[1 AVL树的概念:](#1 AVL树的概念:)
[2 AVL树更新平衡因子流程:](#2 AVL树更新平衡因子流程:)
[2.1 插入节点](#2.1 插入节点)
[2.2 继续向上更新平衡因子](#2.2 继续向上更新平衡因子)
[2.3 更新结束](#2.3 更新结束)
[3 AVL的旋转](#3 AVL的旋转)
[3.1 右单旋](#3.1 右单旋)
[右旋 RotateR 实现步骤](#右旋 RotateR 实现步骤)
[3.2 左单旋](#3.2 左单旋)
[左旋 RotateL 实现步骤](#左旋 RotateL 实现步骤)
[3.3 右左双旋](#3.3 右左双旋)
[3.4 左右双旋](#3.4 左右双旋)
[4 判断树是否平衡](#4 判断树是否平衡)
[5 源码实现](#5 源码实现)
前言:
因为二叉搜索树虽然可以缩短查找效率,但如果数据有序或者接近,二叉搜索树将退化为单只树,查找元素相当于在顺序表中搜索元素,效率低下。
下面的AVL树将解决该问题:
1 AVL树的概念:
一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:
- 它的左右子树都是AVL树
- 左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)

这里的加入平衡因子的计算是右 - 左
2 AVL树更新平衡因子流程:
AVL更新平衡因子及其判断这棵树是否需要平衡处理的流程如下:
插入一个节点(可能会影响该节点的祖先节点)
- 按照搜索树规则插入
- 更新插入节点的祖先节点的平衡因子
a 插入在父节点的左边,父节点的平衡因子--
b 插入在父节点的右边,父节点的平衡因子++
新节点插入后进行判断父亲节点的平衡因子:
c 父节点平衡因子 == 0,父节点所在子树高度不变,不在继续往上更新,插入结束
d 父节点平衡因子 == 1 / -1,父节点所在子树高度变了,继续往上更新
e 父节点平衡因子 == 2 / -2,父节点所在子树已经不平衡了,需要旋转处理
更新中不可能出现其他值,因为插入节点之前是AVL树。
2.1 插入节点
插入新节点cur

2.2 继续向上更新平衡因子


2.3 更新结束
当继续向上更新到cur指向根节点,parent指向空 更新平衡因子结束;
或者当bf == 2 进行旋转调整后,更新平衡因子结束。

AVL树插入节点更新平衡因子逻辑代码:
cpp
bool Insert(const pair<K,V>& kv)
{
if (_root == nullptr)
{
_root = new Node(kv);
return true;
}
Node* parent = nullptr; //记录走过的上一个节点的位置
Node* cur = _root;
//1 查找要插入的位置
while (cur)
{
if (cur->_kv.first < kv.first)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_kv.first > kv.first)
{
parent = cur;
cur = cur->_left;
}
else
{
return false; //key 已经有了
}
}
//2 找到空位置,链接插入新节点
//error 因为 cur是局部变量出了作用域就销毁了,没有形成链接
//cur = new Node(key);
//return true;
//链接方法
//找到空位置,还需要找到该节点的父亲位置
cur = new Node(kv);
//判断链接在左边还是在右边
if (kv.first > parent->_kv.first)
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
//因为这里的使用的是三叉链表
cur->_parent = parent; //记录新插入节点的父亲节点
//3 更新平衡因子
while (parent)
{
//先更新插入节点的父亲节点的平衡因子
if (cur == parent->_left)
{
parent->_bf--;
}
else
{
parent->_bf++;
}
//然后判断父节点的平衡因子是否需要继续往上更新
if (parent->_bf == 0)
{
break; //已经平衡直接退出
}
else if (parent->_bf == 1 || parent->_bf == -1)
{
//继续往上更新平衡因子
cur = parent;
parent = parent->_parent;
}
else if (parent->_bf == 2 || parent->_bf == -2)
{
//当前子树有问题,需要进行旋转调整平衡
break; //旋转后平衡退出
}
else
{
assert(false);
}
}
return true;
}
3 AVL的旋转
当平衡因子是 2 或则 -2 时,需要进行旋转来调整平衡
常见的不平衡的四种情况:

3.1 右单旋
右单旋的场景:
当插入新节点是单纯的左边高,通过右单旋可以达到平衡
h == 0是可以直观的看到左边子树高于右边子树,这里就是单纯的左边高,需要进行右单旋转
h == 1新增节点导致的也是单纯的左边高

接下来通过抽象图来分析:
这里的新增节点也是单纯的左边高

右单旋方法:
因为这里是左边高,所以使用右单旋转来维持平衡
旋转方法:右旋, 把b子树变成60(不平衡点)的左边,再把60变成30的右边

右旋 RotateR 实现步骤
暂存关键节点指针
提取父节点 parent 的左孩子 subL 以及 subL 的右子树 subLR,用于后续指针调整。若 subL 为空则旋转无法进行。
调整子树挂载关系
将 subLR 挂载为 parent 的新左子树。若 subLR 非空,需同步更新其父指针指向 parent,确保双向链接正确性。
核心旋转操作
将 parent 节点作为 subL 的右子树挂载,并更新两者的父子指针关系。此步骤完成节点位置交换,形成右旋后的拓扑结构。
处理上层父节点链接
检查 parent 是否为根节点:
- 若为根节点,直接将
subL设为新根,其父指针置空; - 若非根节点,需判断
parent原属于其父节点ppNode的左或右分支,将subL顶替至对应位置,并更新subL的父指针指向ppNode。
更新平衡因子
旋转后 subL 与 parent 的平衡因子均重置为 0,因左子树高度差已通过旋转消除。

关键代码逻辑示例
右单旋逻辑代码:
cpp
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
//注意:
//当subLR子树不为空的时候,修正三叉链表
parent->_left = subLR;
if (subLR) //这里的subLR可能为空,所以需要判断一下
{
subLR->_parent = parent;
}
subL->_right = parent;
//这里因为不平衡点也可能是一个子树,所以这里要记录它的父节点
Node* ppNode = parent->_parent;
parent->_parent = subL;
//如果不平衡点是根节点,其父节点直接置空
if (parent == _root)
{
_root = subL;
_root->_parent = nullptr;
}
else
{
//如果不平衡点不是是根节点
if (ppNode->_left == parent)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}
subL->_parent = ppNode;
}
//更新平衡因子
subL->_bf = parent->_bf = 0;
}
3.2 左单旋
左单旋的场景:
当插入新节点是单纯的右边高,通过左单旋调整平衡

左单旋方法:
因为这里是单纯的右边高,所以使用左单旋转来维持平衡
旋转方法:左单旋, 把b子树变成30(不平衡点)的右边,再把30变成60的左边

左旋 RotateL 实现步骤
暂存关键节点
提取父节点 parent 的右孩子 subR 和 subR 的左子树 subRL。这两个节点是旋转过程中的关键桥梁,后续操作依赖它们的临时存储。
转接子树关系
将 subRL 挂载为 parent 的右孩子。若 subRL 非空,需同步更新其父指针指向 parent,确保子树父子关系双向绑定。
完成旋转核心操作
将 parent 挂载到 subR 的左孩子位置,建立 subR 与 parent 的父子关系。此时原结构中的右子树 subR 上升为新的局部根节点。
处理上层父节点对接
检查 parent 是否为整棵树的根节点:
- 若为根节点,直接将
subR设为新根,并将其父指针置空。 - 若非根节点,通过
ppNode(原parent的父节点)判断parent原属左/右分支,将subR顶替parent的位置,并绑定subR与ppNode的父子关系。
平衡因子重置
旋转后,subR 和 parent 的平衡因子均置为 0。此操作针对右右失衡场景,旋转后局部子树高度恢复平衡。
关键代码逻辑示例
cpp
//左单旋转
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
//三叉链表修改指向
parent->_right = subRL;
if (subRL)
{
subRL->_parent = parent;
}
subR->_left = parent;
//这里的不平衡点可能是子树,所以需要修改不平衡点的父节点
Node* ppNode = parent->_parent;
parent->_parent = subR;
//(1 如果不平衡点是根节点 其父节点直接置空)
if (parent == _root)
{
_root = subR;
_root->_parent = nullptr;
}
else
{
//(2 如果不平衡点不是根节点 重新判断并修改其父节点的指向)
if (ppNode->_left == parent)
{
ppNode->_left = subR;
}
else
{
ppNode->_right = subR;
}
subR->_parent = ppNode;
}
//最后更新平衡因子
parent->_bf = subR->_bf = 0;
}
3.3 右左双旋
右左双旋场景:
具体例子分析:
这里的不平衡因子 parent.bf ==2 ,subL.bf == -1 ,右边高进行左单旋转,旋转后变成左边高 parent.bf == -2,subR.bf ==1, 左边高需要进行右单旋,结果我们发现,进入了不平衡循环。
所以这里就不能使用单旋转,需要使用双旋来解决问题。

a) 这里的不平衡形状是个折线,因为这里是右边高,左边高,经过对左边高subR进行右单旋转,变 成不平衡的斜线形状 ,该情况就变成了单纯的右边高(左单旋可以直接处理的情况)

b) 然后对不平衡点进行单纯左单旋后即可达到平衡

右左双旋方法:
a) h == 0 的时候,subRL的平衡因子等于0,没有左右子树,直接进行右左双旋。

b) 在b子树下插入新节点,导致右边高,左边高,subRL的平衡因子等于-1,新节点插入在左子树,引发旋转。

c ) 在c子树下插入新节点,导致右边高,左边高,subRL的平衡因子等于1,新节点插入在右子树,引发旋转。

RL双旋(右左双旋)实现步骤
旋转操作步骤
对父节点parent的右子树失衡(右子树的左子树过重)执行双旋:
- 对
parent的右孩子subR执行右单旋(RotateR),使subR的左子树subRL上升为局部根节点。 - 对原根节点
parent执行左单旋(RotateL),最终以subRL为新的根节点完成平衡。
平衡因子更新规则
平衡因子的调整基于旋转前subRL节点的初始值(bf),分为三种情况:
情况1:subRL.bf = -1
- 新节点插入在
subRL的左子树。 - 更新后:
subRL.bf = 0
subR.bf = 1
parent.bf = 0
情况2:subRL.bf = 1
- 新节点插入在
subRL的右子树。 - 更新后:
subRL.bf = 0
subR.bf = 0
parent.bf = -1
情况3:subRL.bf = 0
subRL为新增节点(无子树)。- 更新后:
subRL.bf = 0
subR.bf = 0
parent.bf = 0
非法平衡因子(非-1/0/1)应触发断言异常。
代码实现示例
cpp
//右左双旋
void RotateRL(Node* parent)
{
//用于更新平衡因子
Node* subR = parent->_right;
Node* subRL = subR->_left;
int bf = subRL->_bf;
//首先这里的右单旋是对旋转点的右孩子节点进行右单旋
RotateR(parent->_right);
//然后再对不平衡的节点进行左单旋
RotateL(parent);
//接下来是更新平衡因子
if (bf == -1)
{
//当subRL的平衡因子等于-1,新节点插入在左子树
//直接更新平衡因子
subRL->_bf = 0;
subR->_bf = 1;
parent->_bf = 0;
}
else if (bf == 1)
{
//当subRL的平衡因子等于1,新节点插入在右子树
subRL->_bf = 0;
subR->_bf = 0;
parent->_bf = -1;
}
else if (bf == 0)
{
//当subRL的平衡因子等于0,没有左右子树
subRL->_bf = 0;
subR->_bf = 0;
parent->_bf = 0;
}
else
{
assert(false);
}
}
3.4 左右双旋
左右双旋场景:
当出现左边高,右边的高的情况,需要进行左右双旋处理
左右双旋方法:
a) subLR的平衡因子等于0说明是新增的节点(没有左右子树)。

b )在b子树下插入新节点,导致左边高,右边高,subLR的平衡因子等于-1说明是在subLR的左子树进行插入的,引发旋转。

c ) 在c子树下插入新节点,导致左边高,右边高,subLR的平衡因子等于1说明是在subLR的右子树进行插入的,引发旋转。

左右双旋(LR旋转)实现步骤
核心场景
父节点parent左子树偏高、左子树的右子树偏高(左子树的右孩子过重),属于LR失衡,必须先对左子树左单旋,再对父节点右单旋完成修正。
执行步骤
- 预存关键指针与原始平衡因子
保存父节点左孩子subL、subL的右孩子subLR,提前记录subLR旋转前的平衡因子bf,用于后续更新。 - 两步旋转
① 对parent的左孩子subL执行左单旋 ,把LR结构转为LL结构;
② 对根节点parent执行右单旋,完成整体平衡。 - 依据
subLR原始bf分三种情况更新平衡因子bf = -1:新节点插在subLR左子树
subLR=0、subL=0、parent=1bf = 1:新节点插在subLR右子树
subLR=0、subL=-1、parent=0bf = 0:subLR就是新插入节点
subLR、subL、parent三者平衡因子全部置0
- 非法数值触发断言,做容错校验。
代码实现示例
cpp
//左右双旋
void RotateLR(Node* parent)
{
//用于更新平衡因子
Node* subL = parent->_left;
Node* subLR = subL->_right;
//这里使用subLR的平衡因子来判断平衡因子的更新的几种情况
int bf = subLR->_bf; //因为旋转会导致subLR->_bf平衡因子更新,这里先记录subLR的平衡因子
//这里因为是左边高,右边高
//1)以不平衡节点的左孩子节点为旋转点进行左单旋
RotateL(parent->_left);
//2)经过单纯的左单旋后,变成单纯的左边高,再以不平衡点作为旋转点进行右单旋
RotateR(parent);
//旋转后,进行平衡因子的更新
if (bf == -1)
{
//当subLR的平衡因子等于-1说明是在subLR的左子树进行插入的
subLR->_bf = 0;
subL->_bf = 0;
parent->_bf = 1;
}
else if (bf == 1)
{
//subLR的平衡因子等于1说明是在subLR的右子树进行插入的
subLR->_bf = 0;
subL->_bf = -1;
parent->_bf = 0;
}
else if (bf == 0)
{
//subLR的平衡因子等于0说明是新增的节点(没有左右子树)
subLR->_bf = 0;
subL->_bf = 0;
parent->_bf = 0;
}
else
{
assert(false);
}
}
4 判断树是否平衡
通过判断左右子树的高度差是否小于2,还可以再加上判断AVL树的平衡因子是否正确 来判断是否平衡
cpp
//判断是否树是否平衡
bool _IsBalance(Node* root)
{
if (root == nullptr)
{
return true;
}
//判断左右子树的高度差是否小于2
int leftHeight = _Height(root->_left);
int rightHeight = _Height(root->_right);
if (abs(rightHeight- leftHeight) >= 2)
{
return false;
}
//判断AVL树的平衡因子是否正确
if ((rightHeight - leftHeight) != root->_bf)
{
//如果当前子树的高度左右子树的高度差 是否等于当前节点平衡因子
cout << root->_kv.first<<"false" << endl;
return false;
}
//继续递归判断左右子树
return _IsBalance(root->_left) && _IsBalance(root->_right);
}
补充:
计算AVL树高:
cpp
//计算树的高度
int _Height(Node* root)
{
if (root == nullptr)
{
return 0;
}
return max(_Height(root->_left),_Height(root->_right)) + 1;
}
计算该树的总结点个数:
cpp
//计算插入节点个数
int _Size(Node* root)
{
return root == nullptr ? 0 : _Size(root->_left) + _Size(root->_right) + 1;
}
AVL树删除逻辑:
1 按照搜索树规则进行删除
2 删除后更新平衡因子
3 出现不平衡通过旋转调整
当出现bug的时候,可以采用下方的方法:
借助打印和日志来快速锁定范围
5 源码实现
AVL树完整源码实现如下:
cpp
#pragma once
#include<assert.h>
#include<iostream>
#include<vector>
using namespace std;
template<class K, class V>
struct AVLTreeNode
{
//平衡二叉树使用三叉链表
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;
pair<K,V> _kv;
int _bf; //balance factor 平衡因子
//等价下方形式
//AVLTreeNode<K, V>* _left;
//AVLTreeNode<K, V>* _right;
//K _key;
//V _value;
//构造
AVLTreeNode(const pair<K, V>& kv)
:_left(nullptr)
, _right(nullptr)
,_parent(nullptr)
,_kv(kv)
,_bf(0)
{}
};
template<class K, class V>
class AVLTree
{
public:
typedef AVLTreeNode<K, V> Node;
//插入
bool Insert(const pair<K, V>& kv)
{
if (_root == nullptr)
{
_root = new Node(kv);
return true;
}
Node* parent = nullptr; //记录走过的上一个节点的位置
Node* cur = _root;
//1 查找要插入的位置
while (cur)
{
if (cur->_kv.first < kv.first)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_kv.first > kv.first)
{
parent = cur;
cur = cur->_left;
}
else
{
return false; //key 已经有了
}
}
//2 找到空位置,链接插入新节点
//error 因为 cur是局部变量出了作用域就销毁了,没有形成链接
//cur = new Node(key);
//return true;
//链接方法
//找到空位置,还需要找到该节点的父亲位置
cur = new Node(kv);
//判断链接在左边还是在右边
if (kv.first > parent->_kv.first)
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
//因为这里的使用的是三叉链表
cur->_parent = parent; //记录新插入节点的父亲节点
//3 更新平衡因子
while (parent)
{
//先更新插入节点的父亲节点的平衡因子
if (cur == parent->_left)
{
parent->_bf--;
}
else
{
parent->_bf++;
}
//然后判断父节点的平衡因子是否需要继续往上更新
if (parent->_bf == 0)
{
break; //已经平衡直接退出
}
else if (parent->_bf == 1 || parent->_bf == -1)
{
//继续往上更新平衡因子
cur = parent;
parent = parent->_parent;
}
else if (parent->_bf == 2 || parent->_bf == -2)
{
//当前子树有问题,需要进行旋转调整平衡
//第一种情况
//根据平衡因子判断是左单旋 还是 右单旋转
if (parent->_bf == -2 && cur->_bf == -1)
{
//负值,显然是左边高,需要进行右单旋转
RotateR(parent);
}
else if (parent->_bf == 2 && cur->_bf == 1)
{
//正值,显然是右边高,需要进行左单旋转
RotateL(parent);
}
else if (parent->_bf == 2 && cur->_bf == -1)
{
//右左双旋
//不平衡是一个折线(右边高,左边高)
RotateRL(parent);
}
else if (parent->_bf == -2 && cur->_bf == 1)
{
//双旋
//(先左边高,右边高,折线)
RotateLR(parent);
}
break; //旋转后平衡退出
}
else
{
assert(false);
}
}
return true;
}
//查找
Node* Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (key > cur->_kv.first)
{
cur = cur->_right;
}
else if (key < cur->_kv.first)
{
cur = cur->_left;
}
else
{
return cur;
}
}
return nullptr; //找不到返回空
}
//中序遍历
//通常使用 友元或者缺省参数或者套一层
//这里使用套一层
void InOrder()
{
_InOrder(_root);
}
//右单旋转
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
//注意:
//当subLR子树不为空的时候,修正三叉链表
parent->_left = subLR;
if (subLR) //这里的subLR可能为空,所以需要判断一下
{
subLR->_parent = parent;
}
subL->_right = parent;
//这里因为不平衡点也可能是一个子树,所以这里要记录它的父节点
Node* ppNode = parent->_parent;
parent->_parent = subL;
//如果不平衡点是根节点,其父节点直接置空
if (parent == _root)
{
_root = subL;
_root->_parent = nullptr;
}
else
{
//如果不平衡点不是是根节点
if (ppNode->_left == parent)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}
subL->_parent = ppNode;
}
//更新平衡因子
subL->_bf = parent->_bf = 0;
}
//左单旋转
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
//三叉链表修改指向
parent->_right = subRL;
if (subRL)
{
subRL->_parent = parent;
}
subR->_left = parent;
//这里的不平衡点可能是子树,所以需要修改不平衡点的父节点
Node* ppNode = parent->_parent;
parent->_parent = subR;
//(1 如果不平衡点是根节点 其父节点直接置空)
if (parent == _root)
{
_root = subR;
_root->_parent = nullptr;
}
else
{
//(2 如果不平衡点不是根节点 重新判断并修改其父节点的指向)
if (ppNode->_left == parent)
{
ppNode->_left = subR;
}
else
{
ppNode->_right = subR;
}
subR->_parent = ppNode;
}
//最后更新平衡因子
parent->_bf = subR->_bf = 0;
}
//右左双旋
void RotateRL(Node* parent)
{
//用于更新平衡因子
Node* subR = parent->_right;
Node* subRL = subR->_left;
int bf = subRL->_bf;
//首先这里的右单旋是对旋转点的右孩子节点进行右单旋
RotateR(parent->_right);
//然后再对不平衡的节点进行左单旋
RotateL(parent);
//接下来是更新平衡因子
if (bf == -1)
{
//当subRL的平衡因子等于-1,新节点插入在左子树
//直接更新平衡因子
subRL->_bf = 0;
subR->_bf = 1;
parent->_bf = 0;
}
else if (bf == 1)
{
//当subRL的平衡因子等于1,新节点插入在右子树
subRL->_bf = 0;
subR->_bf = 0;
parent->_bf = -1;
}
else if (bf == 0)
{
//当subRL的平衡因子等于0,没有左右子树
subRL->_bf = 0;
subR->_bf = 0;
parent->_bf = 0;
}
else
{
assert(false);
}
}
//左右双旋
void RotateLR(Node* parent)
{
//用于更新平衡因子
Node* subL = parent->_left;
Node* subLR = subL->_right;
//这里使用subLR的平衡因子来判断平衡因子的更新的几种情况
int bf = subLR->_bf; //因为旋转会导致subLR->_bf平衡因子更新,这里先记录subLR的平衡因子
//这里因为是左边高,右边高
//1)以不平衡节点的左孩子节点为旋转点进行左单旋
RotateL(parent->_left);
//2)经过单纯的左单旋后,变成单纯的左边高,再以不平衡点作为旋转点进行右单旋
RotateR(parent);
//旋转后,进行平衡因子的更新
if (bf == -1)
{
//当subLR的平衡因子等于-1说明是在subLR的左子树进行插入的
subLR->_bf = 0;
subL->_bf = 0;
parent->_bf = 1;
}
else if (bf == 1)
{
//subLR的平衡因子等于1说明是在subLR的右子树进行插入的
subLR->_bf = 0;
subL->_bf = -1;
parent->_bf = 0;
}
else if (bf == 0)
{
//subLR的平衡因子等于0说明是新增的节点(没有左右子树)
subLR->_bf = 0;
subL->_bf = 0;
parent->_bf = 0;
}
else
{
assert(false);
}
}
//判断是否树是否平衡
bool IsBalance()
{
return _IsBalance(_root);
}
int Height()
{
return _Height(_root);
}
int Size()
{
return _Size(_root);
}
private:
//计算插入节点个数
int _Size(Node* root)
{
return root == nullptr ? 0 : _Size(root->_left) + _Size(root->_right) + 1;
}
//计算树的高度
int _Height(Node* root)
{
if (root == nullptr)
{
return 0;
}
return max(_Height(root->_left),_Height(root->_right)) + 1;
}
//判断是否树是否平衡
bool _IsBalance(Node* root)
{
if (root == nullptr)
{
return true;
}
//判断左右子树的高度差是否小于2
int leftHeight = _Height(root->_left);
int rightHeight = _Height(root->_right);
if (abs(rightHeight- leftHeight) >= 2)
{
return false;
}
//判断AVL树的平衡因子是否正确
if ((rightHeight - leftHeight) != root->_bf)
{
//如果当前子树的高度左右子树的高度差 是否等于当前节点平衡因子
cout << root->_kv.first<<"false" << endl;
return false;
}
//继续递归判断左右子树
return _IsBalance(root->_left) && _IsBalance(root->_right);
}
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_kv.first << " " << root->_kv.second << endl;
_InOrder(root->_right);
}
Node* _root = nullptr;
};
void TestAVLTree()
{
//int a[] = {5,3,7,1,4,6,8,0,2};
//AVLTree<int, int> t1;
//for (auto e : a)
//{
// t1.Insert({e,e});
//}
//t1.InOrder();
int a[] = {8,3,1,10,6,4,7,14,13};
//int a[] = {1,3,8,6,10,4};
//int a[] = {4,2,6,1,3,5,15,7,16,14}; //双旋测试
AVLTree<int, int> t1;
for (auto e : a)
{
cout << "Insert:" << e << "->" << t1.IsBalance() << endl;
t1.Insert({e,e});
}
t1.InOrder();
cout << t1.IsBalance() << endl;
}
void TestAVLTree2()
{
//随机数测试
const int N = 1000000;
vector<int> v;
v.reserve(N);
srand(time(0));
for (size_t i = 0; i < N;i++)
{
v.push_back(rand()+i);
}
size_t begin2 = clock();
AVLTree<int, int> t;
for (auto e : v)
{
t.Insert(make_pair(e,e));
}
size_t end2 = clock();
cout << "Insert:" << end2 - begin2 << endl;
cout << t.IsBalance() << endl;
//计算一下树的高度和节点的个数
cout <<"Tree Height:" << t.Height() << endl;
cout <<"Tree Size:" << t.Size() << endl;
}