文章目录
- 1.介绍
- 1.1定义
- 1.2来源
- 1.3概念
- 1.特性
- 2.平衡因子[ Balance Factor-- _bf ]
- 2.BST==>AVL
- 1.示例分析
- 2.情况分类
- 3.代码剖析
- 3.1左左型-右单旋
- 3.2右右型-左单旋
- 3.3左右型-左右旋
- 3.4右左型:右左旋
- 3.5总图
- 3.完整代码
- 3.1AVLTree.h
- 3.2Test.cpp
1.介绍
1.1定义
AVL树 – 平衡二叉树 – 平衡二叉搜索(排序)树 – 高度平衡搜索树
Balanced Binary Tree (BBT)
1.2来源
AVL树得名于它的发明者G. M. Adelson-Velsky和E. M. Landis,他们在1962年的论文《An algorithm for the organization of information》中发表了它。
二叉搜索树可以缩短查找的效率,但在数据有序或接近有序时它将退化为单支树,查找元素相当于在顺序表中搜索,效率低下。两位俄罗斯的数学家发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。
1.3概念
1.特性
- 一棵空树或左右两个子树高度差绝对值不超过1
- 左右两个子树也都是一棵高度平衡搜索树
2.平衡因子[ Balance Factor-- _bf ]
- 结点的平衡因子 == 右子树高度 - 左子树高度
- | _bf | <= 1
- AVL树不一定有平衡因子, 使用平衡因子只是一种较为简单的实现方式
2.BST==>AVL
[设定 _bf = 右子树高度 - 左子树高度]
1.示例分析
先看一下下面的图 了解一下什么叫做旋转 以及旋转的目的
2.情况分类
3.代码剖析
3.1左左型-右单旋
void RotateRight(Node* dad){Node* Grandpa = dad->_parent;Node* sonL = dad->_left;Node* sonLR = sonL->_right;//dad连接sonLR sonLR不空-继承dad 为空不继承dad->_left = sonLR;if (sonLR)sonLR->_parent = dad;//sonL连接dad dad继承sonLsonL->_right = dad;dad->_parent = sonL;//G为空 表明dad为根结点 if (Grandpa == nullptr){//更新根结点_root = sonL;//更新根结点成员属性_root->_parent = nullptr;}else{//父连子if (Grandpa->_left == dad)Grandpa->_left = sonL;elseGrandpa->_right = sonL;//子继承父sonL->_parent = Grandpa;}//更新_bfsonL->_bf = dad->_bf = 0;}
3.2右右型-左单旋
void RotateLeft(Node* dad)
{Node* Grandpa = dad->_parent;Node* sonR = dad->_right;Node* sonRL = sonR->_left;//dad连接sonRL sonRL不空继承dad 为空不继承dad->_right = sonRL;if (sonRL)sonRL->_parent = dad;//sonR连接dad dad继承sonRsonR->_left = dad;dad->_parent = sonR;//Grandpa为空--dad为根节点 更新后 sonR为根节点 根节点的_parent置空if (Grandpa == nullptr){_root = sonR;_root->_parent = nullptr;}//不为空 依实际连接else{//父连子if (Grandpa->_left == dad)Grandpa->_left = sonR;elseGrandpa->_right = sonR;//子继承父sonR->_parent = Grandpa;}//左旋目的达到 更新_bfdad->_bf = sonR->_bf = 0;
}
3.3左右型-左右旋
void RotateLR(Node* dad)
{Node* sonL = dad->_left;Node* sonLR = sonL->_right;int bf = sonLR->_bf;RotateLeft(sonL);RotateRight(dad);if (bf == 1){sonLR->_bf = 0;sonL->_bf = -1;dad->_bf = 0;}else if (bf == -1){sonLR->_bf = 0;sonL->_bf = 0;dad->_bf = 1;}else if (bf == 0){sonLR->_bf = 0;sonL->_bf = 0;dad->_bf = 0;}else{assert(false);}
}
3.4右左型:右左旋
void RotateRL(Node* dad)
{Node* sonR = dad->_right;Node* sonRL = sonR->_left;int bf = sonRL->_bf;//最终根结点的_bfRotateLeft(dad->_right);RotateRight(dad);if (bf == 1){sonRL->_bf = 0;dad->_bf = -1;sonR->_bf = 0;}else if (bf == -1){sonRL->_bf = 0;dad->_bf = 0;sonR->_bf = 1;}else if (bf == 0){sonRL->_bf = 0;dad->_bf = 0;sonR->_bf = 0;1}else{assert(false);}
}
3.5总图
3.完整代码
3.1AVLTree.h
#pragma once
#include <iostream>
#include <list>
#include <vector>
#include <algorithm>
#include <array>
#include <time.h>
#include <queue>
#include <stack>
#include <string>
#include <set>
#include <map>
#include <functional>
#include <assert.h>
#include <math.h>
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> _pair;int _bf; // balance factorAVLTreeNode(const pair<K, V>& pair):_left(nullptr), _right(nullptr), _parent(nullptr), _pair(pair), _bf(0){}
};//高度平衡搜索树
template<class K, class V>
class AVLTree
{typedef AVLTreeNode<K, V> Node;
public://插入--创建二叉树bool Insert(const pair<K, V>& pair){//空树--new结点if (_root == nullptr){_root = new Node(pair);return true;}//非空--插入//1.定位到合适位置Node* parent = nullptr;Node* cp = _root;while (cp){if (pair.first > cp->_pair.first){parent = cp;cp = cp->_right;}else if (pair.first < cp->_pair.first){parent = cp;cp = cp->_left;}else{//搜索树不可有数据重复 -- 插入失败return false;}}//2.链接cp = new Node(pair);if (pair.first < parent->_pair.first){parent->_left = cp;}else{parent->_right = cp;}//cp继承parentcp->_parent = parent;//构建AVL树while (parent){//一、更新平衡因子//插入结点在右子树if (cp == parent->_right){parent->_bf++;}//插入结点在左子树else{parent->_bf--;}//二、分类讨论// _bf == 1/-1 原为0 现高度受到影响// 回溯直至遇到根源结点 即_bf==2/-2的结点if (parent->_bf == 1 || parent->_bf == -1){parent = parent->_parent;cp = cp->_parent;}//_bf == 0 不做处理 原为-1/1 现已满足 不继续更新else if (parent->_bf == 0){break;}else if (parent->_bf == 2 || parent->_bf == -2){//旋转处理目的://1.使得当前子树平衡 2.降低当前子树的高度//左单旋if (parent->_bf == 2 && cp->_bf == 1){RotateL(parent);}//右单旋else if (parent->_bf == -2 && cp->_bf == -1){RotateR(parent);}//左右旋else if (parent->_bf == -2 && cp->_bf == 1){RotateLR(parent);}//右左旋else if (parent->_bf == 2 && cp->_bf == -1){RotateRL(parent);}else{assert(false);}break;}else{assert(false);}}return true;}//中序遍历void InOrder(){_InOrder(_root);cout << endl;}//高度接口int Height(){return _Height(_root);}//判断是否满足AVL树平衡bool IsBalance(){return _IsBalance(_root);}private:// 中序遍历void _InOrder(Node* root){if (root == nullptr){return;}_InOrder(root->_left);cout << root->_pair.first << " ";_InOrder(root->_right);}//高度接口int _Height(Node* root){if (root == NULL)return 0;int leftH = _Height(root->_left);int rightH = _Height(root->_right);return leftH > rightH ? leftH + 1 : rightH + 1;}//判断是否满足AVL树平衡bool _IsBalance(Node* root){if (root == NULL){return true;}int leftH = _Height(root->_left);int rightH = _Height(root->_right);if (rightH - leftH != root->_bf){cout << root->_pair.first << "Abnormal node balance factor!" << endl;return false;}return abs(leftH - rightH) < 2&& _IsBalance(root->_left)&& _IsBalance(root->_right);}//左单旋void RotateL(Node* parent){//记录GrandpaNode* Grandpa = parent->_parent;Node* subR = parent->_right;Node* subRL = subR->_left;//parent链接subRL subRL不空继承parent 空没必要继承parent->_right = subRL;if (subRL)subRL->_parent = parent;//subR连接parent parent继承subRsubR->_left = parent;parent->_parent = subR;//Grandpa为空--parent为根节点 更新后 subR为根节点 根节点的_parent置空if (Grandpa == nullptr){_root = subR;_root->_parent = nullptr;}//不为空 依实际连接else{//父连子if (Grandpa->_left == parent){Grandpa->_left = subR;}else{Grandpa->_right = subR;}//子继承父subR->_parent = Grandpa;}parent->_bf = subR->_bf = 0;}//右单旋void RotateR(Node* parent){Node* Grandpa = parent->_parent;Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;subL->_right = parent;parent->_parent = subL;if (parent == _root){_root = subL;_root->_parent = nullptr;}else{if (Grandpa->_left == parent){Grandpa->_left = subL;}else{Grandpa->_right = subL;}subL->_parent = Grandpa;}subL->_bf = parent->_bf = 0;}void RotateLR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RotateL(parent->_left);RotateR(parent);if (bf == 1){parent->_bf = 0;subLR->_bf = 0;subL->_bf = -1;}else if (bf == -1){parent->_bf = 1;subLR->_bf = 0;subL->_bf = 0;}else if (bf == 0){parent->_bf = 0;subLR->_bf = 0;subL->_bf = 0;}else{assert(false);}}void RotateRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);if (bf == 1){subR->_bf = 0;parent->_bf = -1;subRL->_bf = 0;}else if (bf == -1){subR->_bf = 1;parent->_bf = 0;subRL->_bf = 0;}else if (bf == 0){subR->_bf = 0;parent->_bf = 0;subRL->_bf = 0;}else{assert(false);}}private:Node* _root = nullptr;
};void Test_AVLTree1()
{int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };int b[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };AVLTree<int, int> tree;for (auto e : b){tree.Insert(make_pair(e, e));if (tree.IsBalance()){cout << e << "插入成功!" << endl;}else{cout << e << "插入失败!" << endl;}}cout << "此树中序遍历:" << endl;tree.InOrder();if (tree.IsBalance()){cout << "此树为一棵AVL树" << endl;}else{cout << "此树不为一棵AVL树!" << endl;}
}void Test_AVLTree2()
{srand(time(0));const size_t N = 10;AVLTree<int, int> tree;for (size_t i = 0; i < N; ++i){size_t x = rand() + i;tree.Insert(make_pair(x, x));if (tree.IsBalance()){cout << x << "插入成功!" << endl;}else{cout << x << "插入失败!" << endl;}}cout << "此树中序遍历:" << endl;tree.InOrder();if (tree.IsBalance()){cout << "此树为一棵AVL树" << endl;}else{cout << "此树不为一棵AVL树!" << endl;}cout << "此树高度为:" << tree.Height() << endl;
}
3.2Test.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <list>
#include <vector>
#include <algorithm>
#include <array>
#include <time.h>
#include <queue>
#include <stack>
#include <string>
#include <set>
#include <map>
#include <functional>
using namespace std;
#include "AVLTree.h"int main()
{Test_AVLTree1();return 0;
}