文章目录
前言: 普通的二叉搜索树无法保证平衡,也就是 如果有序的插入数据,会导致此二叉搜索树退化为单支,效率会打折扣,所以 有了AVL树,它是可以保证 树的平衡,对于平衡的概念后面会讲,它是怎么保证平衡的?都会讲到,并且 我们要模拟实现 AVL树。
1. AVL树的概念
AVL树就是 可以 绝对保证 平衡的 搜索树,怎么才算平衡呢?
- 平衡:左右子树的高度差 不超过 1。
- AVL树的左右子树都是 AVL树
如何控制 平衡呢?我这里实现用的是平衡因子。也就是说 每个节点都有平衡因子。
平衡因子规则:
- 每个节点 默认的平衡因子为 0
- 节点的平衡因子 = 右子树高度 - 左子树高度
这就能控制平衡了?当然不能,平衡因子是用于 判断 需不需要旋转 的依据。对,是通过旋转来控制平衡的。旋转有 左单旋,右单旋 ,左右双旋,右左双旋转。听起来复杂,没事 会 理清楚的。
插入节点 平衡因子更新规则:
- 新的节点A 插入到 节点B的右边,那么B的平衡因子+ 1
- 新的节点A 插入到 节点B的左边,那么A的平衡因子 - 1
- 插入节点 会 影响 此条路径上的所有祖先
- 插入节点 后,祖先的平衡因子 可能出现 5 种情况:
(1) 祖先的平衡因子变为 0,说明 它原来的平衡因子是 -1 \ 1 。-1 -> 0,说明是插入到它的右边, 1 -> 0, 说明插入到了它的左边;这个时候 就不需要 往上继续更新了,因为 它不可影响到 其他祖先,它很平衡。
(2) 祖先的平衡因子变为 1,-1 。说明 它原来的平衡因子 是 0。0 -> -1,说明是插入到它的左边,0 -> 1,说明是插入到它的右边;这个时候 需不需要 往上更新,需要的,因为 它 影响了 其他祖先。更新到 没有祖先 或者 祖先的平衡因子为 0,就不往上更新了。
(3)祖先的平衡因子变为 2/ -2 ,说明 它原来的平衡因子是 1 \ -1。1 -> 2,说明是插入到它的右边。-1 -> -2,说明是插入到它的左边。这个时候就出问题了,因为不平衡了,高度差 超过 1了,所以 要旋转。
2. 旋转 —— 乾坤大挪移
2.1 左单旋
- 先看这颗抽象树:
a,b,c 都是 子树,h代表树的高度, 3 和 6 的平衡因子给出了已经,就是 右子树高度 - 左子树高度。
那么我有个问题:在哪里插入一个节点会 引发 左单旋 ?
- 首先,在 a 子树 下插入 会 导致 左单旋吗?肯定不会,因为 在 a 下插入节点 会导致 3 节点的平衡因子 变为 0。
- 然后,在 b 子树 下插入,6 节点 的平衡因子 变为 -1,3 节点 受影响吗?肯定受影响,3 节点的平衡因子 变为 2。但是需要注意 这不是 左单旋转可以解决的,因为 插入的节点 对于 6 来说 是插入在了它的左边,它的平衡因子减去 1,对于 3 来说 是它的右树 新增了 一个节点 它的平衡因子 加 1。先不讲 这个情况。
- 最后是 在 c子树 下插入,6 节点 的平衡因子 变为 1,3 节点的平衡因子 变为 2。这就需要左单旋转。
所以 左单旋 的平衡因子条件:
- 出问题的节点 平衡因子 为 2,它的右子树平衡因子为 1。
- 出问题的节点 右子树 比 左子树 高,所以 要让 此树 的 左子树 高度 +1 。
口诀: 右边单纯高,左单旋
- 将出问题的节点 (3节点)往下压 ,它的
右子树
(6节点) 变为 它原来的右子树
(6节点)的左子树
(b子树)。 - 出问题的节点(3节点),变为 它的原来的右子树(6节点) 的左子树。
图解:
就这样 完成 左单旋,但是有人会问:你怎么知道?上面的 6节点的 左子树可以 做3节点的 右子树?还有 3节点 可以作为 6节点的 左子树。
这就是 二叉搜索树呀。
- 第一个问题:6节点的 左子树节点 绝对比 3节点 要大,因为 插入 的时候 比 3 大插入到它的右子树,所以 3节点 的右子树 中所有的节点 都是要大于 3节点的。
- 第二个问题:6节点是 3节点的右子树,所以 3节点 小于 6节点,所以 3节点可以作为 6节点 的 左子树。
总结: 右边单纯高,左单旋,本质就是 这颗树整体的高度 减一,去弥补 左子树。再直白点就是 让出问题的节点 下去,填补左子树,从而达到平衡。
2.2 右单旋
其实 就是 上面的例子反一下,不会讲的很细。但是 逻辑还在。
在 a子树下插入 会导致 右单旋转:
很明显,6节点 的平衡因子为 -2,需要旋转。
所以 右单旋 的平衡因子条件:
- 出问题的节点 平衡因子 为 -2,它的左子树平衡因子为 -1。
- 出问题的节点 左子树 比 右子树 高,所以 要让 此树 的 右子树 高度 +1。
口诀: 左边单纯高,右单旋
- 将出问题的节点 (6节点)往下压 ,它的
左子树
(3节点) 变为 它原来的左子树
(3节点)的右子树
(b子树)。 - 出问题的节点(6节点),变为 它原来的
左子树
(3节点) 的右子树。
图解:
这就是 右单选。
2.3 右左双旋
这个其实用 具体点的图 好讲,因为 它得先右旋一下,再左旋一下,比较复杂,所以 我给出三种具像图:
1. h 为 0,也就是 高度为 0。
(1)先对 平衡因子 为-1 的节点 (6节点) ,进行右单旋
可以看到,先在是什么情况?平衡因子出问题的是 2,它的右子树平衡因子是1。单纯的右边高,所以要怎么办?左单旋。
(2) 再对 平衡因子 为 2 的节点 ,进行左单旋
2. h = 1的情况
那么现在 新插入的节点 插入到 5节点 的左边或者右边 都会造成 右左双旋
那么 对 6节点先进行右单旋:
再对 3节点 进行 左单旋:
3. 当 h=2 的情况:
这种情况就多了,但是我只以一种为例子:
(1) 对 6进行 右单旋:
(2) 对 3节点 进行 左单旋
总结一下:我们 抽像的想一下
这个左右双旋,无非就是将 b这颗子树 的根节点 推上去 成为 3节点和6节点 的根,然后 将 b子树 的左子树 分给 3节点,右子树 分给 6节点。就类似这样:
就是 推上去,再瓜分掉其左右子树。这确实有点抽象。
说说结论:先对 出现问题的节点的右子树 进行 右单旋,再对出现问题的节点 进左单旋。当然 平衡因子这里有细节,实现的时候,我们再讲。
2.4 左右双旋
这种情况就需要 左右双旋:
图解如下:
(1) 先 对3节点 进行 左单旋
(2) 再 对6节点 进行右单旋
就是这样,完成了 左右双旋。
2.5 对旋转的总结
什么时候需要旋转?当出现 平衡因子 为 2或者 -2 时。
- 左单旋:出现问题的节点 的平衡因子 为 2,它的右子树 平衡因子 为 1。本质 :新增的节点 单纯的使得 右树增高。
- 右左双旋 :出现问题的节点 的平衡因子 为 2,它的右子树 平衡因子 为 -1。本质:新增的节点 对于平衡因子为2 来说 它是插入到右树,但是对于平衡因子 为 -1,它是插入到了 左边。
- 右单旋:出现问题的节点 的平衡因子为 -2,它的左子树 平衡因子为 -1。本质:新增的节点 单纯的使得 左树增高。
- 左右双旋:出现问题的节点 的平衡因子 为 -2,它的左子树 平衡因子为 1。本质:新增的节点 对于平衡因子为-2的来说,它是插入到了左树,但是对于平衡因子为 1的来说,它是插入到了 右树。
就这些情况,上面 一 一 对应的 都讲到了,只是理论实现,我们下面进行实践。
3. AVL树的实现
3.1 AVL树的 节点
template<class K, class V>
struct AVL_node
{
AVL_node<K, V>* left_;
AVL_node<K, V>* right_;
AVL_node<K, V>* parents_;
std::pair<K, V> kv_;
int ef_; //Equilibrium factor 平衡因子
AVL_node(const std::pair<K, V>& kv)
:left_(nullptr),
right_(nullptr),
parents_(nullptr),
kv_(kv),
ef_(0)
{}
};
用三叉链来 实现 AVL树:
有指向左树的指针,右树的指针;指向父亲的指针;它的节点数据 是一个 pair<K,V>,当然还有 平衡因子 ef_。
3.2 AVL树的私有成员以及构造
AVL树 只需要记录根节点,就可以了。构造也很简单。
template<class K,class V>
class AVL_tree
{
typedef AVL_node<K,V> Node;
private:
Node* _root;
public:
AVL_tree()
:_root(nullptr)
{}
};
3.3 AVL树的插入
这是重点,首先 AVL树是一个搜索树,所以得遵循搜索树的逻辑去 插入节点 ;其次 我们要更新平衡因子;然后根据 平衡因子 来判断 需不要 旋转。对于平衡因子的更新,以及 是否要旋转 ,上文都有讲解。
public:
bool insert(const std::pair<K,V>& node)
{
if (_root == nullptr)
{
_root = new Node(node);
return true;
}
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (node.first > cur->kv_.first)
{
parent = cur;
cur = cur->right_;
}
else if (node.first< cur->kv_.first)
{
parent = cur;
cur = cur->left_;
}
else
{
assert(false);
}
}
cur = new Node(node);
if (parent->kv_.first > cur->kv_.first)
{
parent->left_ = cur;
cur->parents_ = parent;
}
else
{
parent->right_ = cur;
cur->parents_ = parent;
}
/ 控制平衡
更新平衡因子
while (parent)
{
if (cur == parent->left_)
{
parent->ef_--;
}
else
{
parent->ef_++;
}
if (parent->ef_ == 0)
break;
else if (parent->ef_ == 1 || parent->ef_ == -1)
{
继续往上更新 平衡因子
cur = parent;
parent = cur->parents_;
}
else if (parent->ef_ == 2 || parent->ef_ == -2)
{
// 旋转
if (parent->ef_ == 2 && parent->right_->ef_ == 1)
{
// 左单旋转
revolov_L(parent);
}
else if (parent->ef_ == 2 && parent->right_->ef_ == -1)
{
/// 右左双旋
revolov_RL(parent);
}
else if (parent->ef_ == -2 && parent->left_->ef_ == -1)
{
右单旋
revolov_R(parent);
}
else if (parent->ef_ == -2 && parent->right_->ef_ == 1)
{
/// 左右双旋
revolov_LR(parent);
}
else
{
assert(false);
}
break;
}
}
}
3.3.1 左单旋代码实现
issue 就是 问题,英文翻译一锤。还有那个 issue_node_parent 有三种情况:
- 为空,说明 issue_node 是根节点
- issue_node 可能 连接在 issue_node_parent 的左边
- issue_node 可能 连接在 issue_node_parent 的右边
这种情况 就是 左单旋:
void revolov_L(Node* issue_node)
{
Node* issue_Rnode = issue_node->right_;
Node* issue_Rnode_L = issue_Rnode->left_;
Node* issue_node_parent = issue_node->parents_;
issue_node->right_ = issue_Rnode_L;
if (issue_Rnode_L)
{
issue_Rnode_L->parents_ = issue_node;
}
issue_Rnode->left_ = issue_node;
issue_node->parents_ = issue_Rnode;
if (issue_node_parent == nullptr)
{
_root = issue_Rnode;
issue_Rnode->parents_ = nullptr;
}
else
{
if (issue_node_parent->left_ == issue_node)
issue_node_parent->left_ = issue_Rnode;
else
issue_node_parent->right_ = issue_Rnode;
issue_Rnode->parents_ = issue_node_parent;
}
issue_node->ef_ = issue_Rnode->ef_ = 0;
}
其实 旋转的关键 就是在于 改变 三叉链的 链接关系。
代码结合 图解:
(1)
issue_node->right_ = issue_Rnode_L;
// 判读是否为空
if (issue_Rnode_L)
{
issue_Rnode_L->parents_ = issue_node;
}
(2)
issue_Rnode->left_ = issue_node;
issue_node->parents_ = issue_Rnode;
// 改变 issue_Rnode 的 parents
if (issue_node_parent == nullptr)
{
_root = issue_Rnode;
issue_Rnode->parents_ = nullptr;
}
else
{
if (issue_node_parent->left_ == issue_node)
issue_node_parent->left_ = issue_Rnode;
else
issue_node_parent->right_ = issue_Rnode;
issue_Rnode->parents_ = issue_node_parent;
}
就是这样式的,最后 更新一下 平衡因子 就 OK了。
3.3.2 右单旋代码实现
void revolov_R(Node* issue_node)
{
Node* issue_Lnode = issue_node->left_;
Node* issue_Lnode_R = issue_Lnode->right_;
Node* issue_node_parent = issue_node->parents_;
issue_node->left_ = issue_Lnode_R;
if (issue_Lnode_R)
{
issue_Lnode_R->parents_ = issue_node;
}
issue_Lnode->right_ = issue_node;
issue_node->parents_ = issue_Lnode;
if (issue_node_parent == nullptr)
{
_root = issue_Lnode;
issue_Lnode->parents_ = nullptr;
}
else
{
if (issue_node_parent->left_ == issue_node)
issue_node_parent->left_ = issue_Lnode;
else
issue_node_parent->right_ = issue_Lnode;
issue_Lnode->parents_ = issue_node_parent;
}
issue_node->ef_ = issue_Lnode->ef_ = 0;
}
这就是 和上面 反一下,逻辑一样的。
3.3.3 右左双旋代码实现
void revolov_RL(Node* issue_node)
{
revolov_R(issue_node->right_);
revolov_L(issue_node);
}
3.3.4 左右双旋代码实现
void revolov_LR(Node* issue_node)
{
revolov_L(issue_node->left_);
revolov_R(issue_node);
}
3.4 AVL树的中序遍历
我们都知道 搜索树 的中序遍历就是 有序的。所以 可以用来 先验证 一下 我们上面 实现的 AVL树是否为 搜索树。
public:
void InOrder()
{
_InOrder(_root);
}
private:
void _InOrder(Node* root)
{
if (root == NULL)
return;
_InOrder(root->left_);
std::cout << root->kv_.first << ":" << root->kv_.second << std::endl;
_InOrder(root->right_);
}
好,现在 我们 来验证一下:
int main()
{
AVL_tree<int, int> t;
//int a[] = {5,4,3,2,1,0};
//int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
for (auto e : a)
{
t.insert(std::make_pair(e, e));
}
t.InOrder();
return 0;
}
运行结果:
没问题 就是 搜索树。
3.5 AVL树 验证 平衡
验证平衡的关键 就是 :左右子树的差值 ,是否 与平衡因子 相等。
有人说:直接 查看 平衡因子就行了,这是不可以的,因为平衡因子 是由我们来控制的,它不一定能 反馈真实情况。
public:
bool IsBalance()
{
return _IsBalance(_root);
}
private:
int Height(Node* root)
{
if (root == NULL)
return 0;
int leftHeight = Height(root->left_);
int rightHeight = Height(root->right_);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
bool _IsBalance(Node* root)
{
if (root == NULL)
return true;
// 对当前树进行检查
int leftHeight = Height(root->left_);
int rightHeight = Height(root->right_);
if (rightHeight - leftHeight != root->ef_)
{
std:: cout << root->kv_.first << "现在是:" << root->ef_ << std::endl;
std:: cout << root->kv_.first << "应该是:" << rightHeight - leftHeight << std::endl;
return false;
}
return abs(rightHeight - leftHeight) < 2
&& _IsBalance(root->left_)
&& _IsBalance(root->right_);
}
好,验证一下是否平衡:
int main()
{
AVL_tree<int, int> t;
int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
for (auto e : a)
{
t.insert(std::make_pair(e, e));
std::cout << "Insert" << e << ":" << t.IsBalance() << std::endl;
}
return 0;
}
发现 插入 14 的时候,导致 6节点 的平衡因子 出错了,平衡因子有问题 绝对会影响 后序的插入。
这是为什么呢?
插入 14节点,会怎样? 右左双旋
先对 15节点 右单旋
再对 6 进行 左单旋转
6节点 的平衡因子 是 -1,但是 因为 对它进行了 左单旋,将它的平衡因子 置成了 0。这就是问题所在,所以双旋需要控制平衡因子,怎么控制呢?
3.5.1 控制双旋的平衡因子
3.5.1.1 右左双旋
其实这块,可以翻上去 看看 我画的 那三种情况:
旋转完后, 6 的平衡因子 有两种情况 :
- 6 的平衡因子为 0,h为 0,所以 b是新增节点
- 6 的平衡因子为 1,说明 新增的节点 是 b树的 左边
旋转完后,3 的平衡因子 有两种情况: - 3 的平衡因子为 0,h为 0,所以 b是新增节点
- 3 的平衡因子为 -1,说明 新增的节点是 b树的 右边
总结一下:出问题的节点 双旋完之后,它的平衡因子 必然为0;关键就是 那个平衡因子为 -1的节点,双旋完后,它的平衡因子需要控制,它的平衡因子控制看的是 b树的情况。
我还是 画画 图吧。
(1) 第一种情况,这个比较简单
(2) 新增节点在 b树的右边
(3) 新增节点在 b树的左边
从这其实 也能再次抽象 理解 :
将 那个新增节点的根节点,推上去作为此支树的根,然后让出问题的节点和问题节点的右树瓜分它的 左子树和右子树。 没瓜分到的 所以就会 导致 平衡因子 为 1或者 -1。
代码实现:
void revolov_RL(Node* issue_node)
{
Node* issue_Rnode = issue_node->right_;
Node* issue_Rnode_L = issue_Rnode->left_;
int flag = 0;
if (issue_Rnode_L->ef_ == 1)
{
flag = 1;
}
if (issue_Rnode_L->ef_ == -1)
{
flag = -1;
}
revolov_R(issue_Rnode);
revolov_L(issue_node);
if (flag == 1)
{
issue_node->ef_ = -1;
}
if (flag == -1)
{
issue_Rnode->ef_ = 1;
}
}
昂,再来 验证一下上面那个 平衡:
这就解决问题了。
3.5.1.2 左右双旋
有了上面的基础,其实 左右双旋也是可以实现的,主要是 看 b树情况:
只不过就反一下而已,我直接画图:
(1)
(2)
(3)
代码实现:
void revolov_LR(Node* issue_node)
{
Node* issue_Lnode = issue_node->left_;
Node* issue_Lnode_R = issue_Lnode->right_;
int flag = 0;
if (issue_Lnode_R->ef_ == 1)
{
flag = 1;
}
if (issue_Lnode_R->ef_ == -1)
{
flag = -1;
}
revolov_L(issue_node->left_);
revolov_R(issue_node);
if (flag == 1)
{
issue_Lnode->ef_ = -1;
}
if (flag == -1)
{
issue_node->ef_ = 1;
}
}
就是这样,大家下去好好思考。
4. AVL树 代码汇总
#pragma once
#include<iostream>
#include<assert.h>
namespace AVL
{
template<class K, class V>
struct AVL_node
{
AVL_node<K, V>* left_;
AVL_node<K, V>* right_;
AVL_node<K, V>* parents_;
std::pair<K, V> kv_;
int ef_; //Equilibrium factor 平衡因子
AVL_node(const std::pair<K, V>& kv)
:left_(nullptr),
right_(nullptr),
parents_(nullptr),
kv_(kv),
ef_(0)
{}
};
template<class K,class V>
class AVL_tree
{
typedef AVL_node<K,V> Node;
private:
Node* _root;
public:
AVL_tree()
:_root(nullptr)
{}
private:
void revolov_L(Node* issue_node)
{
Node* issue_Rnode = issue_node->right_;
Node* issue_Rnode_L = issue_Rnode->left_;
Node* issue_node_parent = issue_node->parents_;
issue_node->right_ = issue_Rnode_L;
if (issue_Rnode_L)
{
issue_Rnode_L->parents_ = issue_node;
}
issue_Rnode->left_ = issue_node;
issue_node->parents_ = issue_Rnode;
if (issue_node_parent == nullptr)
{
_root = issue_Rnode;
issue_Rnode->parents_ = nullptr;
}
else
{
if (issue_node_parent->left_ == issue_node)
issue_node_parent->left_ = issue_Rnode;
else
issue_node_parent->right_ = issue_Rnode;
issue_Rnode->parents_ = issue_node_parent;
}
issue_node->ef_ = issue_Rnode->ef_ = 0;
}
void revolov_R(Node* issue_node)
{
Node* issue_Lnode = issue_node->left_;
Node* issue_Lnode_R = issue_Lnode->right_;
Node* issue_node_parent = issue_node->parents_;
issue_node->left_ = issue_Lnode_R;
if (issue_Lnode_R)
{
issue_Lnode_R->parents_ = issue_node;
}
issue_Lnode->right_ = issue_node;
issue_node->parents_ = issue_Lnode;
if (issue_node_parent == nullptr)
{
_root = issue_Lnode;
issue_Lnode->parents_ = nullptr;
}
else
{
if (issue_node_parent->left_ == issue_node)
issue_node_parent->left_ = issue_Lnode;
else
issue_node_parent->right_ = issue_Lnode;
issue_Lnode->parents_ = issue_node_parent;
}
issue_node->ef_ = issue_Lnode->ef_ = 0;
}
void revolov_RL(Node* issue_node)
{
Node* issue_Rnode = issue_node->right_;
Node* issue_Rnode_L = issue_Rnode->left_;
int flag = 0;
if (issue_Rnode_L->ef_ == 1)
{
flag = 1;
}
if (issue_Rnode_L->ef_ == -1)
{
flag = -1;
}
revolov_R(issue_Rnode);
revolov_L(issue_node);
if (flag == 1)
{
issue_node->ef_ = -1;
}
if (flag == -1)
{
issue_Rnode->ef_ = 1;
}
}
void revolov_LR(Node* issue_node)
{
Node* issue_Lnode = issue_node->left_;
Node* issue_Lnode_R = issue_Lnode->right_;
int flag = 0;
if (issue_Lnode_R->ef_ == 1)
{
flag = 1;
}
if (issue_Lnode_R->ef_ == -1)
{
flag = -1;
}
revolov_L(issue_node->left_);
revolov_R(issue_node);
if (flag == 1)
{
issue_Lnode->ef_ = -1;
}
if (flag == -1)
{
issue_node->ef_ = 1;
}
}
public:
bool insert(const std::pair<K,V>& node)
{
if (_root == nullptr)
{
_root = new Node(node);
return true;
}
Node* cur = _root;
Node* parent = nullptr;
while (cur)
{
if (node.first > cur->kv_.first)
{
parent = cur;
cur = cur->right_;
}
else if (node.first< cur->kv_.first)
{
parent = cur;
cur = cur->left_;
}
else
{
assert(false);
}
}
cur = new Node(node);
if (parent->kv_.first > cur->kv_.first)
{
parent->left_ = cur;
cur->parents_ = parent;
}
else
{
parent->right_ = cur;
cur->parents_ = parent;
}
/ 控制平衡
更新平衡因子
while (parent)
{
if (cur == parent->left_)
{
parent->ef_--;
}
else
{
parent->ef_++;
}
if (parent->ef_ == 0)
break;
else if (parent->ef_ == 1 || parent->ef_ == -1)
{
继续往上更新 平衡因子
cur = parent;
parent = cur->parents_;
}
else if (parent->ef_ == 2 || parent->ef_ == -2)
{
// 旋转
if (parent->ef_ == 2 && parent->right_->ef_ == 1)
{
// 左单旋转
revolov_L(parent);
}
else if (parent->ef_ == 2 && parent->right_->ef_ == -1)
{
/// 右左双旋
revolov_RL(parent);
}
else if (parent->ef_ == -2 && parent->left_->ef_ == -1)
{
右单旋
revolov_R(parent);
}
else if (parent->ef_ == -2 && parent->right_->ef_ == 1)
{
/// 左右双旋
revolov_LR(parent);
}
else
{
assert(false);
}
break;
}
}
}
public:
void InOrder()
{
_InOrder(_root);
}
private:
void _InOrder(Node* root)
{
if (root == NULL)
return;
_InOrder(root->left_);
std::cout << root->kv_.first << ":" << root->kv_.second << std::endl;
_InOrder(root->right_);
}
public:
bool IsBalance()
{
return _IsBalance(_root);
}
private:
int Height(Node* root)
{
if (root == NULL)
return 0;
int leftHeight = Height(root->left_);
int rightHeight = Height(root->right_);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
bool _IsBalance(Node* root)
{
if (root == NULL)
return true;
// 对当前树进行检查
int leftHeight = Height(root->left_);
int rightHeight = Height(root->right_);
if (rightHeight - leftHeight != root->ef_)
{
std:: cout << root->kv_.first << "现在是:" << root->ef_ << std::endl;
std:: cout << root->kv_.first << "应该是:" << rightHeight - leftHeight << std::endl;
return false;
}
return abs(rightHeight - leftHeight) < 2
&& _IsBalance(root->left_)
&& _IsBalance(root->right_);
}
};
}
5.结尾
以上就是 AVL树 的实现,有问题 的私信,或者评论。