AVL树
目录
[四、平衡因子(balance factor)](#四、平衡因子(balance factor))
一、AVL树的由来
在前苏联科学家G.M.A delson-V elsky和E.M.Landis的论文
《An algorithm for the organization of information》中发表
二、AVL树的概念
**AVL树:**最先发明的自平衡二叉搜索树
(注:通过控制高度差去控制平衡,又称高度平衡二叉搜索树)
**性质:**左右子树都是AV树,左右子树的高度差的绝对值不超过1
问:为什么要求高度差不超过1,而不是高度差为0?
在一棵树是两个节点、四个节点的情况下,高度差最好就是1

三、AVL树的优势
AVL树的节点数量和分布与完全二叉树类似
高度可以控制在logN
增删查改的效率可以控制在O(logN)
四、平衡因子(balance factor)
每个节点都有一个平衡因子
任何节点的平衡因子等于右子树的高度减去左子树的高度
平衡因子的大小:0、1、-1
平衡的AVL树

不平衡的非AVL树

五、AVL树的实现
5.1.AVL树的结构
树节点结构
cpp
template<class K,class V>
struct AVLTreeNode
{
pair<K, V> _kv;
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;//需要parent指针
int _bf;//平衡因子
AVLTreeNode(const pair<K, V>& kv)
:_kv(kv)
,_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_bf(0)
{ }
};
树的结构
cpp
template<class K,class V>
class AVLTree
{
typedef AVLTreeNode<K, V> Node;
public:
//...
private:
Node* _root = nullptr;
};
5.2.AVL树的插入
**步骤1:**按照二叉搜索树的方式插入新节点
**步骤2:**判断是否需要更新平衡因子,如果出现问题,则需更新平衡因子
5.3.平衡因子的更新
更新规则
- 平衡因子 = 右子树高度 - 左子树高度
- 只有子树高度变化才会影响当前节点的平衡因子
- 新节点在parent的右子树,parent的平衡因子++
- 新节点在parent的左子树,parent的平衡因子--
- parent所在子树高度是否变化决定了是否继续向上更新
更新的停止条件
**情况1:**更新后的parent平衡因子等于0
更新中的parent平衡因子变化为 -1 --> 0 或者 1 --> 0
说明更新前parent子树一边高一边低,新增的节点插入在低的那一边
插入后parent子树的高度不变,parent子树符合平衡要求
不会影响parent的父节点的平衡因子,因为高度不变,更新结束
**情况2:**更新后的parent平衡因子等于1或者-1
更新中的parent平衡因子变化为 0 --> 1 或者 0 --> -1
说明更新前parent子树两边一样高,新增的节点插入在任意两边
插入后parent子树一边高一边低,parent子树仍符合平衡要求
会影响parent的父节点的平衡因子,因为高度增加1,需要继续向上更新
**情况3:**更新后的parent平衡因子等于2或者-2
更新中的parent平衡因子变化为 1 --> 2 或者 -1 --> -2
说明更新前parent子树一边高一边低,新增的节点插入在高的那一边
插入后parent子树高的那边更高,parent子树不符合平衡要求,需要旋转处理
旋转后,parent子树平衡,parent子树恢复到插入节点之前的高度,需要继续向上更新

**极端情况:**不断更新到根节点,根节点的平衡因子是1或-1,更新结束
终止条件总结
更新后的parent平衡因子为0

更新到根节点,根节点平衡因子为-1或1

插入以及平衡因子计算代码
cpp
#pragma once
template<class K,class V>
struct AVLTreeNode
{
pair<K, V> _kv;
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;//需要parent指针
int _bf;//平衡因子
AVLTreeNode(const pair<K, V>& kv)
:_kv(kv)
,_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_bf(0)
{}
};
template<class K,class V>
class AVLTree
{
typedef AVLTreeNode<K, V> Node;
public:
bool Insert(const pair<K, V>& kv)
{
//如果为空树
if (_root == nullptr)
{
//将根节点赋为新节点
_root = new Node(kv);
//返回插入成功
return true;
}
//父节点为空
Node* parent = nullptr;
//当前节点为根节点
Node* cur = _root;
//遍历二叉树
//循环条件为cur不为空
while (cur)
{
//如果当前节点的key值小于新节点的key值
if (cur->_kv.first < kv.first)
{
//更新父节点
parent = cur;
//更新当前节点(指向右子树)
cur = cur->_right;
}
else if (cur->_kv.first > kv.first)//如果当前节点的key值大于新节点的key值
{
//更新父节点
parent = cur;
//更新当前节点(指向左子树)
cur = cur->_left;
}
else//当前节点的key值等于新节点的key值
{
//存在重复值,返回插入失败
return false;
}
}
//将当前节点(指向空)赋为新节点
cur = new Node(kv);
//如果父节点的key值小于新节点的key值
if (parent->_kv.first < kv.first)
{
//将新节点赋为父节点的右子树
parent->_right = cur;
}
else//如果父节点的key值大于新节点的key值
{
//将新节点赋为父节点的左子树
parent->_left = cur;
}
//将当前节点与父节点链接
cur->_parent = parent;
//控制平衡
//更新平衡因子
//循环条件为parent不为空
while (parent)
{
//如果新节点在parent的左边
if (cur == parent->_left)
{
//parent的平衡因子--
parent->_bf--;
}
else//如果新节点在parent的右边
{
//parent的平衡因子++
parent->_bf++;
}
//如果更新后parent的平衡因子为0
if (parent->_bf == 0)
{
//停止更新
break;
}
else if (parent->_bf == 1 || parent->_bf == -1)//如果更新后parent的平衡因子为1或-1
{
//继续向上更新
cur = parent;
parent = parent->_parent;
}
else if (parent->_bf == 2 || parent->_bf == -2)//如果更新后parent的平衡因子为2或-2
{
//旋转
break;
}
else
{
assert(false);
}
}
return true;
}
private:
Node* _root = nullptr;
};
5.4.旋转的原则
保持搜索树的规则
让树从不平衡变为平衡,降低树的高度
左单旋、右单旋、左右双旋、右左双旋
左单旋
一棵根为10的树,有a、b、c三棵高度为h的子树(h>=0,符合AVL树)
(注:10可能是整棵树的根,也可能是局部子树的根)
在a子树中插入一个新节点,a子树的高度从h变为h+1,不断向上更新平衡因子
导致10的平衡因子从1变为2,10为根的树左右高度差超过1,违反了平衡规则
因为10 < b子树 < 15,将b变为10的右子树,将10变为15的左子树,将15变为这棵树新的根
既控制了树的平衡,又把这棵树的高度恢复为h+2,符合旋转规则

左单旋代码
cpp
void RotateL(Node* parent)
{
//获取节点15
Node * subR = parent->_right;
//获取子树b
Node * subRL = subR->_left;
//节点10的右子树更新为子树b
parent->_right = subRL;
//如果子树b不为空树
if (subRL)
{
//子树b的父亲节点更新为节点10
subRL->_parent = parent;
}
//获取parent节点的父亲节点
Node * pParent = parent->_parent;
//节点15的左子树更新为节点10
subR->_left = parent;
//节点10的父亲节点更新为节点15
parent->_parent = subR;
//如果旋转前,parent为根
if (pParent == nullptr)
{
//更新根节点
_root = subR;
//将根节点的父亲节点置空
subR->_parent = nullptr;
}
else//如果旋转前,parent为局部子树
{
//如果parent为父亲节点的左子树
if (parent == pParent->_left)
{
//让parent的父亲节点的左子树指向节点15
pParent->_left = subR;
}
else//如果parent为父亲节点的右子树
{
//让parent的父亲节点的右子树指向节点15
pParent->_right = subR;
}
//更新节点15的父亲节点为parent的父亲节点
subR->_parent = pParent;
}
//更新节点15和节点10的平衡因子
parent->_bf = subR->_bf = 0;
}
右单旋
一棵根为10的树,有a、b、c三棵高度为h的子树(h>=0,符合AVL树)
(注:10可能是整棵树的根,也可能是局部子树的根)
在a子树中插入一个新节点,a子树的高度从h变为h+1,不断向上更新平衡因子
导致10的平衡因子从1变为2,10为根的树左右高度差超过1,违反了平衡规则
因为5 < b子树 < 10,将b变为10的左子树,将10变为5的右子树,将5变为这棵树新的根
既控制了树的平衡,又把这棵树的高度恢复为h+2,符合旋转规则

**情况1:**插入前a、b、c高度h == 0

**情况2:**插入前a、b、c高度h == 1

**情况3:**插入前a、b、c高度为h == 2
b、c为x、y、z中的任意一种情况
a必须为x的情况
(注:当a为y、z时,插入节点后y、z高度h+1,y、z自身需要旋转)
a中插入节点会引发10节点旋转的插入位置有4个
(左子树的左边与右边,右子树的左边与右边)
所以一共有3 * 3 * 4 == 36种情况

**情况4:**插入前a、b、c高度为h == 3
b、c可以是x、y-C中的任意一种情况
a如果是x,插入位置可以是4个叶子的任意孩子位置,有8种情况
a如果是y-C,4个叶子保留3个有4种情况,插入位置在有两个节点的任意孩子位置,有4种情况
所以一共有15 * 15 * ( 8 + 4 * 4 )= 5400种情况

右单旋代码
cpp
//右单旋
void RotateR(Node* parent)
{
//获取节点5
Node* subL = parent->_left;
//获取子树b
Node* subLR = subL->_right;
//节点10的左子树更新为子树b
parent->_left = subLR;
//如果子树b不为空子树
if (subLR)
{
//子树b的父亲节点更新为节点10
subLR->_parent = parent;
}
//获取parent节点的父亲节点
Node* pParent = parent->_parent;
//节点5的右子树更新为节点10
subL->_right = parent;
//节点10的父亲节点更新为节点5
parent->_parent = subL;
//如果旋转前,parent为根
if (parent == _root)
{
//更新根节点
_root = subL;
//将根节点的父亲节点置空
_root->_parent = nullptr;
}
else//如果旋转前,parent为局部子树
{
//如果parent为父亲节点的左子树
if (pParent->_left == parent)
{
//让parent的父亲节点的左子树指向节点5
pParent->_left = subL;
}
else//如果parent为父亲节点的右子树
{
//让parent的父亲节点的右子树指向节点5
pParent->_right = subL;
}
//更新节点5的父亲节点为parent的父亲节点
subL->_parent = pParent;
}
//更新节点5和节点10的平衡因子
subL->_bf = 0;
parent->_bf = 0;
}
左边高时,如果插入位置不是a子树,而是插入在b子树
b子树的高度从h变为h+1,引发了旋转,右单旋后依旧不平衡
右单旋解决的纯粹的左边高,所以插入在b子树,10为根的子树不再是单纯的左边高
对于10是左边高,5是右边高的情况,需要旋转两次才能解决
以5为旋转点进行一个左单旋,以10为旋转点进行一个右单旋
情况1: 插入前a、b、c高度h == 0
**情况2:**插入前a、b、c高度h == 1

左右双旋
节点8变成新的根节点,节点5变成8的左子树,节点10变成8的右子树
节点8的左子树变为节点5的右子树,节点8的右子树变为节点10的左子树
可以根据节点8的平衡因子来判断是那种场景

左右双旋代码
cpp
//左右双旋
void RotateLR(Node* parent)
{
//获取节点5
Node* subL = parent->_left;
//获取节点8
Node* subLR = subL->_right;
//获取节点8的平衡因子
int bf = subLR->_bf;
//节点5左单旋
RotateL(parent->_left);
//节点10右单旋
RotateR(parent);
//如果节点8的平衡因子插入后变为-1
if (bf == -1)
{
//旋转后节点8的平衡因子更新为0
subLR->_bf = 0;
//旋转后节点5的平衡因子更新为0
subL->_bf = 0;
//旋转后节点10的平衡因子更新为1
parent->_bf = 1;
}
else if (bf == 1)//如果节点8的平衡因子插入后变为1
{
//旋转后节点8的平衡因子更新为0
subLR->_bf = 0;
//旋转后节点5的平衡因子更新为-1
subL->_bf = -1;
//旋转后节点10的平衡因子更新为0
parent->_bf = 0;
}
else if(bf == 0)//如果节点8的平衡因子插入后变为0
{
//旋转后节点8的平衡因子更新为0
subLR->_bf = 0;
//旋转后节点5的平衡因子更新为0
subL->_bf = 0;
//旋转后节点10的平衡因子更新为0
parent->_bf = 0;
}
else//保证平衡因子出现异常时能够知晓
{
assert(false);
}
}
右左双旋
节点12变成新的根节点,节点10变成12的左子树,节点15变成12的右子树
节点12的左子树变为节点10的右子树,节点12的右子树变为节点15的左子树
可以根据节点12的平衡因子来判断是那种场景

右左双旋代码
cpp
void RotateRL(Node* parent)
{
//获取节点15
Node * subR = parent->_right;
//获取节点12
Node * subRL = subR->_left;
//获取节点12的平衡因子
int bf = subRL->_bf;
//节点15右单旋
RotateR(parent->_right);
//节点10左单旋
RotateL(parent);
if (bf == 0)//如果节点12的平衡因子插入后变为0
{
//旋转后节点15的平衡因子更新为0
subR->_bf = 0;
//旋转后节点12的平衡因子更新为0
subRL->_bf = 0;
//旋转后节点10的平衡因子更新为0
parent->_bf = 0;
}
else if (bf == 1)//如果节点12的平衡因子插入后变为1
{
//旋转后节点15的平衡因子更新为0
subR->_bf = 0;
//旋转后节点12的平衡因子更新为0
subRL->_bf = 0;
//旋转后节点10的平衡因子更新为-1
parent->_bf = -1;
}
else if (bf == -1)//如果节点12的平衡因子插入后变为-1
{
//旋转后节点15的平衡因子更新为1
subR->_bf = 1;
//旋转后节点12的平衡因子更新为0
subRL->_bf = 0;
//旋转后节点10的平衡因子更新为0
parent->_bf = 0;
}
else//保证平衡因子出现异常时能够知晓
{
assert(false);
}
}
5.5.AVL树实现总代码
cpp
#pragma once
#include <iostream>
#include "assert.h"
#include "math.h"
using namespace std;
template<class K,class V>
struct AVLTreeNode
{
pair<K, V> _kv;
AVLTreeNode<K, V>* _left;
AVLTreeNode<K, V>* _right;
AVLTreeNode<K, V>* _parent;//需要parent指针
int _bf;//平衡因子
AVLTreeNode(const pair<K, V>& kv)
:_kv(kv)
,_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_bf(0)
{}
};
template<class K,class V>
class AVLTree
{
typedef AVLTreeNode<K, V> Node;
public:
bool Insert(const pair<K, V>& kv)
{
//如果为空树
if (_root == nullptr)
{
//将根节点赋为新节点
_root = new Node(kv);
//返回插入成功
return true;
}
//父节点为空
Node* parent = nullptr;
//当前节点为根节点
Node* cur = _root;
//遍历二叉树
//循环条件为cur不为空
while (cur)
{
//如果当前节点的key值小于新节点的key值
if (cur->_kv.first < kv.first)
{
//更新父节点
parent = cur;
//更新当前节点(指向右子树)
cur = cur->_right;
}
else if (cur->_kv.first > kv.first)//如果当前节点的key值大于新节点的key值
{
//更新父节点
parent = cur;
//更新当前节点(指向左子树)
cur = cur->_left;
}
else//当前节点的key值等于新节点的key值
{
//存在重复值,返回插入失败
return false;
}
}
//将当前节点(指向空)赋为新节点
cur = new Node(kv);
//如果父节点的key值小于新节点的key值
if (parent->_kv.first < kv.first)
{
//将新节点赋为父节点的右子树
parent->_right = cur;
}
else//如果父节点的key值大于新节点的key值
{
//将新节点赋为父节点的左子树
parent->_left = cur;
}
//将当前节点与父节点链接
cur->_parent = parent;
//控制平衡
//更新平衡因子
//循环条件为parent不为空
while (parent)
{
//如果新节点在parent的左边
if (cur == parent->_left)
{
//parent的平衡因子--
parent->_bf--;
}
else//如果新节点在parent的右边
{
//parent的平衡因子++
parent->_bf++;
}
//如果更新后parent的平衡因子为0
if (parent->_bf == 0)
{
//停止更新
break;
}
else if (parent->_bf == 1 || parent->_bf == -1)//如果更新后parent的平衡因子为1或-1
{
//继续向上更新
cur = parent;
parent = parent->_parent;
}
else if (parent->_bf == 2 || parent->_bf == -2)//如果更新后parent的平衡因子为2或-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)//左右双旋
{
RotateLR(parent);
}
else if (parent->_bf == 2 && cur->_bf == -1)//右左双旋
{
RotateRL(parent);
}
else
{
assert(false);
}
break;
}
else
{
assert(false);
}
}
return true;
}
//右单旋
void RotateR(Node* parent)
{
//获取节点5
Node* subL = parent->_left;
//获取子树b
Node* subLR = subL->_right;
//节点10的左子树更新为子树b
parent->_left = subLR;
//如果子树b不为空子树
if (subLR)
{
//子树b的父亲节点更新为节点10
subLR->_parent = parent;
}
//获取parent节点的父亲节点
Node* pParent = parent->_parent;
//节点5的右子树更新为节点10
subL->_right = parent;
//节点10的父亲节点更新为节点5
parent->_parent = subL;
//如果旋转前,parent为根
if (parent == _root)
{
//更新根节点
_root = subL;
//将根节点的父亲节点置空
_root->_parent = nullptr;
}
else//如果旋转前,parent为局部子树
{
//如果parent为父亲节点的左子树
if (pParent->_left == parent)
{
//让parent的父亲节点的左子树指向节点5
pParent->_left = subL;
}
else//如果parent为父亲节点的右子树
{
//让parent的父亲节点的右子树指向节点5
pParent->_right = subL;
}
//更新节点5的父亲节点为parent的父亲节点
subL->_parent = pParent;
}
//更新节点5和节点10的平衡因子
subL->_bf = 0;
parent->_bf = 0;
}
//左单旋
void RotateL(Node* parent)
{
//获取节点15
Node* subR = parent->_right;
//获取子树b
Node* subRL = subR->_left;
//节点10的右子树更新为子树b
parent->_right = subRL;
//如果子树b不为空树
if (subRL)
{
//子树b的父亲节点更新为节点10
subRL->_parent = parent;
}
//获取parent节点的父亲节点
Node* pParent = parent->_parent;
//节点15的左子树更新为节点10
subR->_left = parent;
//节点10的父亲节点更新为节点15
parent->_parent = subR;
//如果旋转前,parent为根
if (pParent == nullptr)
{
//更新根节点
_root = subR;
//将根节点的父亲节点置空
subR->_parent = nullptr;
}
else//如果旋转前,parent为局部子树
{
//如果parent为父亲节点的左子树
if (parent == pParent->_left)
{
//让parent的父亲节点的左子树指向节点15
pParent->_left = subR;
}
else//如果parent为父亲节点的右子树
{
//让parent的父亲节点的右子树指向节点15
pParent->_right = subR;
}
//更新节点15的父亲节点为parent的父亲节点
subR->_parent = pParent;
}
//更新节点15和节点10的平衡因子
parent->_bf = subR->_bf = 0;
}
//左右双旋
void RotateLR(Node* parent)
{
//获取节点5
Node* subL = parent->_left;
//获取节点8
Node* subLR = subL->_right;
//获取节点8的平衡因子
int bf = subLR->_bf;
//节点5左单旋
RotateL(parent->_left);
//节点10右单旋
RotateR(parent);
if (bf == -1)//如果节点8的平衡因子插入后变为-1
{
//旋转后节点8的平衡因子更新为0
subLR->_bf = 0;
//旋转后节点5的平衡因子更新为0
subL->_bf = 0;
//旋转后节点10的平衡因子更新为1
parent->_bf = 1;
}
else if (bf == 1)//如果节点8的平衡因子插入后变为1
{
//旋转后节点8的平衡因子更新为0
subLR->_bf = 0;
//旋转后节点5的平衡因子更新为-1
subL->_bf = -1;
//旋转后节点10的平衡因子更新为0
parent->_bf = 0;
}
else if(bf == 0)//如果节点8的平衡因子插入后变为0
{
//旋转后节点8的平衡因子更新为0
subLR->_bf = 0;
//旋转后节点5的平衡因子更新为0
subL->_bf = 0;
//旋转后节点10的平衡因子更新为0
parent->_bf = 0;
}
else//保证平衡因子出现异常时能够知晓
{
assert(false);
}
}
//右左双旋
void RotateRL(Node* parent)
{
//获取节点15
Node* subR = parent->_right;
//获取节点12
Node* subRL = subR->_left;
//获取节点12的平衡因子
int bf = subRL->_bf;
//节点15右单旋
RotateR(parent->_right);
//节点10左单旋
RotateL(parent);
if (bf == 0)//如果节点12的平衡因子插入后变为0
{
//旋转后节点15的平衡因子更新为0
subR->_bf = 0;
//旋转后节点12的平衡因子更新为0
subRL->_bf = 0;
//旋转后节点10的平衡因子更新为0
parent->_bf = 0;
}
else if (bf == 1)//如果节点12的平衡因子插入后变为1
{
//旋转后节点15的平衡因子更新为0
subR->_bf = 0;
//旋转后节点12的平衡因子更新为0
subRL->_bf = 0;
//旋转后节点10的平衡因子更新为-1
parent->_bf = -1;
}
else if (bf == -1)//如果节点12的平衡因子插入后变为-1
{
//旋转后节点15的平衡因子更新为1
subR->_bf = 1;
//旋转后节点12的平衡因子更新为0
subRL->_bf = 0;
//旋转后节点10的平衡因子更新为0
parent->_bf = 0;
}
else//保证平衡因子出现异常时能够知晓
{
assert(false);
}
}
//中序遍历打印
void InOrder()
{
_InOrder(_root);
cout << endl;
}
//AVL平衡检测
bool IsBalanceTree()
{
return _IsBalanceTree(_root);
}
//AVL高度计算
int Height()
{
return _Height(_root);
}
//AVL节点计算
int Size()
{
return _Size(_root);
}
//AVL查找
Node* Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (cur->_kv.first < key)
{
cur = cur->_right;
}
else if (cur->_kv.first > key)
{
cur = cur->_left;
}
else
{
return cur;
}
}
return nullptr;
}
private:
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_kv.first << ":" << root->_kv.second << endl;
_InOrder(root->_right);
}
int _Height(Node* root)
{
if (root == nullptr)
{
return 0;
}
int leftHeight = _Height(root->_left);
int rightHeight = _Height(root->_right);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
int _Size(Node* root)
{
if (root == nullptr)
{
return 0;
}
return _Size(root->_left) + _Size(root->_right) + 1;
}
bool _IsBalanceTree(Node* root)
{
//空树也是AVL树
if (nullptr == root)
{
return true;
}
//计算pRoot结点的平衡因子
//即pRoot左右子树的高度差
int leftHeight = _Height(root->_left);
int rightHeight = _Height(root->_right);
int diff = rightHeight - leftHeight;
//如果计算出的平衡因子与pRoot的平衡因子不相等
//pRoot平衡因子的绝对值超过1,则一定不是AVL树
if (abs(diff) >= 2)
{
cout << root->_kv.first << "高度差异常" << endl;
return false;
}
if (root->_bf != diff)
{
cout << root->_kv.first << "平衡因子异常" << endl;
return false;
}
//pRoot的左和右如果都是AVL树
//则该树一定是AVL树
return _IsBalanceTree(root->_left) && _IsBalanceTree(root->_right);
}
Node* _root = nullptr;
};
5.6.测试代码
cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include "AVLTree.h"
#include <vector>
//测试插入,中序遍历代码
void TestAVLTree1()
{
AVLTree<int, int> t;
int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
for (auto e : a)
{
t.Insert({ e, e });
}
t.InOrder();
cout << t.IsBalanceTree() << 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.IsBalanceTree() << endl;
cout << "Height:" << t.Height() << endl;
cout << "Size:" << t.Size() << endl;
size_t begin1 = clock();
////确定在的值
///*for (auto e : v)
//{
// t.Find(e);
//}*/
// 随机值
for (size_t i = 0; i < N; i++)
{
t.Find((rand() + i));
}
size_t end1 = clock();
cout << "Find:" << end1 - begin1 << endl;
}
int main()
{
TestAVLTree1();
TestAVLTree2();
return 0;
}
