目录
AVL的定义
平衡二叉查找树:简称平衡二叉树。由前苏联的数学家Adelse-Velskil和Landis在1962年提出的高度平衡的二叉树,根据科学家的英文名也称为AVL树。它具有如下几个性质:
1.可以是空树。
2.假如不是空树,任何一个结点的左子树与右子树都是平衡二叉树,并且高度之差的绝对值不超过1
3.具有二叉查找树所有性质
为什么要调整
平衡二叉树,一定是二叉排序树,之所以将排序树,调整为平衡状态,是为了在二叉排序树近似为链的情况下,增强其查找性能,降低时间复杂度。
树高
记录和更新当前结点的高度是平衡二叉树的核心点,它会告诉你插入或者删除一个节点有没有打破平衡需要进行调整。
树节点
typedef struct TreeAVLNode *treeNode;
struct TreeAVLNode
{
int val;
int depth; //高度
treeNode lChild;
treeNode rChild;
TreeAVLNode(int _val) : val(_val),depth(0), lChild(NULL), rChild(NULL) {}
};
记录更新高度:
void MyAVLTree::update_depth(treeNode& node)
{
if (node == NULL)
{
return;
}
int depth_lChild = get_banlance(node->lChild);
int depth_rChild = get_banlance(node->rChild);
node->depth = depth_lChild > depth_rChild ? depth_lChild : depth_rChild;
node->depth++;
return;
}
int MyAVLTree::get_banlance(treeNode node)
{
if (node == NULL)
{
return 0;
}
return node->depth;
}
int MyAVLTree::get_Node_Banlance(treeNode node)
{
if (node == NULL)
{
return 0;
}
return get_banlance(node->lChild) - get_banlance(node->rChild);
}
/*
a4
b3 c3
d2 f2
g1
字母为节点 数字为高度
如果此时插入一个节点h位置如下:
a5
b4 c4
d3 f3
g2
h1
d3的平衡因子 = g2 - g2左子树 = -2
此时需要调整
*/
树的旋转调整
平衡因子:树的左子树和右子树高度差绝对值。
什么情况下调整:平衡因子 >=2
void MyAVLTree::rr_Rotate(treeNode& node)
{
/*
3 : node 2
2 1 3
1
3的平衡差为2这时候要右旋转 2和3的层次都有变化需要更新一下
2的右孩子给3
3成为2的右孩子
2替代3的位置
*/
treeNode son = node->lChild;
node->lChild = son->rChild;
update_depth(node);
son->rChild = node;
node = son;
update_depth(son);
}
void MyAVLTree::ll_Rotate(treeNode& node)
{
/*
1 : node
2
3
1的平衡差为-2这时候要左旋转
2的左孩子给1
1成为2的左孩子
2替代1的位置
*/
treeNode son = node->rChild;
node->rChild = son->lChild;
update_depth(node);
son->lChild = node;
node = son;
update_depth(son);
}
void MyAVLTree::rl_Rotate(treeNode& node)
{
rr_Rotate(node->rChild);
ll_Rotate(node);
}
void MyAVLTree::lr_Rotate(treeNode& node)
{
ll_Rotate(node->lChild);
rr_Rotate(node);
}
/*
1:node 如果按照 ll转的话 就会成这样 3
3 1
2 2 不行
所以先以3为node先右转 1
3:node 2
2 3 再左转
*/
检查调整
就是判断平衡因子不平衡时判断看是哪种上面4种情况的那一种然后调整
代码:
void MyAVLTree::AVLTree(treeNode& node)
{
int balance = 0;
update_depth(node);
balance = get_Node_Banlance(node);
if (balance > 1)
leftBalance(node);
else if (balance < -1)
rightBalance(node);
else
return;
}
void MyAVLTree::leftBalance(treeNode& node)
{
//左边不平衡 需要右旋转
if (get_Node_Banlance(node->lChild) < 0)
{
//高度差大于0说明是这样的:
/*
4
1
3
*/
lr_Rotate(node);
}
else
{
rr_Rotate(node);
}
}
void MyAVLTree::rightBalance(treeNode& node)
{
//右边不平衡 需要左旋转
if (get_Node_Banlance(node->rChild) > 0)
{
rl_Rotate(node);
}
else
{
ll_Rotate(node);
}
}
树结点的插入
平衡树的插入在查找树的基础上增加了记录更新树高和检查调整函数
代码:
treeNode MyAVLTree::insertAVLNode(treeNode& root,int val)
{
if (root == NULL)
{
root = new TreeAVLNode(val);
update_depth(root);
return root;
}
treeNode tmep = NULL;
if (val < root->val)
{
tmep = insertAVLNode(root->lChild, val);
}
else if (val > root->val)
{
tmep = insertAVLNode(root->rChild, val);
}
if (tmep)
{
AVLTree(root); --检查调整树
}
return tmep;
}
树结点的删除
考虑4种情况:
1.删除结点不带小孩:删了就行
2.删除结点带左小孩:代替自己
3.删除结点带右小孩:代替自己
4.删除结点带2小孩:找中序遍历前继结点或者后继结点代替自己
前3点都很简单:
第4点详细看一下:
有如下二叉查找树
41
13 52
11 34 45 82
40 42 48 60 145
46
中序遍历结果如下:11 .13. 34 .40 .41.42.45.46.48.52.60.82.145
中序遍历的规律是:先左后根再右
假如我们要删除结点52我们该如何调整呢?
找前继或者后继结点 48 . 60
找前继的路径是先左后右 left45 .right48,48的右结点没了就他了
然后把52换成48,把48换成46就行了
找后继先右后左反过来就行
代码:
treeNode MyAVLTree::deleteAVLNode(treeNode& root, int val)
{
if (root == NULL)
{
return NULL;
}
treeNode tmep = NULL;
if (val < root->val)
{
tmep = deleteAVLNode(root->lChild, val);
}
else if (val > root->val)
{
tmep = deleteAVLNode(root->rChild, val);
}
else
{
return removeNodeForAVL(root);
}
if (tmep)
{
AVLTree(root);
}
return tmep;
}
treeNode MyAVLTree::removeNodeForAVL(treeNode& node)
{
treeNode pCur;
treeNode pNext;
pCur = node;
if (pCur->rChild == NULL)
{
node = pCur->lChild;
return pCur;
}
else if (pCur->lChild == NULL)
{
node = pCur->rChild;
return pCur;
}
else
{
pNext = pCur->lChild;
while (pNext->rChild)
{
pCur = pNext;
pNext = pNext->rChild;
}
node->val = pNext->val;
if (pCur != node)
{
pCur->rChild = pNext->lChild;
}
else
{
pCur->lChild = pNext->lChild;
}
return pNext;
}
return NULL;
}
完整代码
AVLTree.h
#ifndef _AVLTREE_H__
#define _AVLTREE_H__
#include<stdio.h>
typedef struct TreeAVLNode *treeNode;
struct TreeAVLNode
{
int val;
int depth; //高度
treeNode lChild;
treeNode rChild;
TreeAVLNode(int _val) : val(_val),depth(0), lChild(NULL), rChild(NULL) {}
};
class MyAVLTree
{
public:
MyAVLTree();
~MyAVLTree();
bool insertNode(int val);
bool deleteNode(int val);
void printfTreeByarrangement();
private:
void freeAllTreeNode(treeNode root);
void rr_Rotate(treeNode& node);
void ll_Rotate(treeNode& node);
void rl_Rotate(treeNode& node);
void lr_Rotate(treeNode& node);
void update_depth(treeNode& node);
int get_banlance(treeNode node);
int get_Node_Banlance(treeNode node);
treeNode insertAVLNode(treeNode& root, int val);
treeNode deleteAVLNode(treeNode& root, int val);
treeNode removeNodeForAVL(treeNode& node);
void AVLTree(treeNode& node);
void leftBalance(treeNode& node);
void rightBalance(treeNode& node);
private:
treeNode m_Root;
};
#endif // !_AVLTREE_H__
AVTTree.cpp
#include"AVLTree.h"
#include<vector>
using namespace std;
MyAVLTree::MyAVLTree()
{
}
MyAVLTree::~MyAVLTree()
{
freeAllTreeNode(m_Root);
}
void MyAVLTree::freeAllTreeNode(treeNode root)
{
if (NULL == root)
{
return;
}
treeNode LChild = root->lChild;
treeNode RChild = root->rChild;
printf("delete:%d \n", root->val);
delete root;
freeAllTreeNode(LChild);
freeAllTreeNode(RChild);
}
void MyAVLTree::rr_Rotate(treeNode& node)
{
/*
3 : node 2
2 1 3
1
3的平衡差为2这时候要右旋转 2和3的层次都有变化需要更新一下
2的右孩子给3
3成为2的右孩子
2替代3的位置
*/
treeNode son = node->lChild;
node->lChild = son->rChild;
update_depth(node);
son->rChild = node;
node = son;
update_depth(son);
}
void MyAVLTree::ll_Rotate(treeNode& node)
{
/*
1 : node
2
3
1的平衡差为-2这时候要左旋转
2的左孩子给1
1成为2的左孩子
2替代1的位置
*/
treeNode son = node->rChild;
node->rChild = son->lChild;
update_depth(node);
son->lChild = node;
node = son;
update_depth(son);
}
void MyAVLTree::rl_Rotate(treeNode& node)
{
/*
1:node 如果按照 ll转的话 就会成这样 3
3 1
2 2 不行
所以先以3为node先右转 1
3:node 2
2 3 再左转
*/
rr_Rotate(node->rChild);
ll_Rotate(node);
}
void MyAVLTree::lr_Rotate(treeNode& node)
{
ll_Rotate(node->lChild);
rr_Rotate(node);
}
void MyAVLTree::update_depth(treeNode& node)
{
if (node == NULL)
{
return;
}
int depth_lChild = get_banlance(node->lChild);
int depth_rChild = get_banlance(node->rChild);
node->depth = depth_lChild > depth_rChild ? depth_lChild : depth_rChild;
node->depth++;
return;
}
int MyAVLTree::get_banlance(treeNode node)
{
if (node == NULL)
{
return 0;
}
return node->depth;
}
int MyAVLTree::get_Node_Banlance(treeNode node)
{
if (node == NULL)
{
return 0;
}
return get_banlance(node->lChild) - get_banlance(node->rChild);
}
bool MyAVLTree::insertNode(int val)
{
treeNode newNode = NULL;
newNode = insertAVLNode(m_Root, val);
if (newNode)
{
return true;
}
else
{
return false;
}
}
bool MyAVLTree::deleteNode(int val)
{
treeNode delNode = NULL;
delNode = deleteAVLNode(m_Root, val);
if (delNode)
{
delete delNode;
return true;
}
else
{
return false;
}
}
void MyAVLTree::AVLTree(treeNode& node)
{
int balance = 0;
update_depth(node);
balance = get_Node_Banlance(node);
if (balance > 1)
leftBalance(node);
else if (balance < -1)
rightBalance(node);
else
return;
}
void MyAVLTree::leftBalance(treeNode& node)
{
//左边不平衡 需要右旋转
if (get_Node_Banlance(node->lChild) < 0)
{
//高度差大于0说明是这样的:
/*
4
1
3
*/
lr_Rotate(node);
}
else
{
rr_Rotate(node);
}
}
void MyAVLTree::rightBalance(treeNode& node)
{
//右边不平衡 需要左旋转
if (get_Node_Banlance(node->rChild) > 0)
{
rl_Rotate(node);
}
else
{
ll_Rotate(node);
}
}
treeNode MyAVLTree::insertAVLNode(treeNode& root,int val)
{
if (root == NULL)
{
root = new TreeAVLNode(val);
update_depth(root);
return root;
}
treeNode tmep = NULL;
if (val < root->val)
{
tmep = insertAVLNode(root->lChild, val);
}
else if (val > root->val)
{
tmep = insertAVLNode(root->rChild, val);
}
if (tmep)
{
AVLTree(root);
}
return tmep;
}
treeNode MyAVLTree::deleteAVLNode(treeNode& root, int val)
{
if (root == NULL)
{
return NULL;
}
treeNode tmep = NULL;
if (val < root->val)
{
tmep = deleteAVLNode(root->lChild, val);
}
else if (val > root->val)
{
tmep = deleteAVLNode(root->rChild, val);
}
else
{
return removeNodeForAVL(root);
}
if (tmep)
{
AVLTree(root);
}
return tmep;
}
treeNode MyAVLTree::removeNodeForAVL(treeNode& node)
{
treeNode pCur;
treeNode pNext;
pCur = node;
if (pCur->rChild == NULL)
{
node = pCur->lChild;
return pCur;
}
else if (pCur->lChild == NULL)
{
node = pCur->rChild;
return pCur;
}
else
{
pNext = pCur->lChild;
while (pNext->rChild)
{
pCur = pNext;
pNext = pNext->rChild;
}
node->val = pNext->val;
if (pCur != node)
{
pCur->rChild = pNext->lChild;
}
else
{
pCur->lChild = pNext->lChild;
}
return pNext;
}
return NULL;
}
void levelOrder(vector<vector<int>> &ret, treeNode root, int level)
{
if (root == NULL) return;
if ((int)ret.size() <= level)
{
ret.push_back(vector<int>());
}
ret[level].push_back(root->val);
levelOrder(ret, root->lChild, level + 1);
levelOrder(ret, root->rChild, level + 1);
}
void MyAVLTree::printfTreeByarrangement()
{
vector<vector<int>> ret;
levelOrder(ret, m_Root, 0);
for (auto arrs : ret)
{
for (auto i : arrs)
{
printf("%d ", i);
}
printf("\n");
}
}
test.cpp
#include"AVLTree.h"
void test()
{
MyAVLTree mytree;
int sum[] = { 3,2,1,4,5,6,7,10,8,9 ,23,56,82,11,13,11,13,145,13,23,4,34,23,52,41,42,48,45,40};
for (auto i : sum)
{
mytree.insertNode(i);
}
mytree.printfTreeByarrangement();
for (auto i : sum)
{
if (mytree.deleteNode(i))
{
mytree.printfTreeByarrangement();
printf("\n");
}
}
}
int main()
{
test();
getchar();
return 0;
}
测试结果