AVL树详解
来源:互联网 发布:电脑人工智能软件 编辑:程序博客网 时间:2024/04/30 04:05
AVL树定义:
AVL树又称为高度平衡的二叉搜索树。它能保持二叉树的高度平衡,尽量降低二叉树的高度,减少树的平均搜索长度。
AVL树性质:
- 左子树和右子树的高度之差的绝对值不超过1
- 树中的每个左子树和右子树都是AVL树
- 每个节点都有一个平衡因子(balance factor--bf),任一节点的平衡因子是-1,0,1。(每个节点的平衡因子等于右子树的高度减去左子树的高度 )
AVL树效率:
一棵AVL树有N个节点,其高度可以保持在lgN,插入/删除/查找的时间复杂度也是lgN。
AVL树节点信息如下:
template<class K, class V>struct AVLTreeNode{K _key; //关键字V _value; AVLTreeNode<K, V>* _parent;//父亲AVLTreeNode<K, V>* _left;//左孩子AVLTreeNode<K, V>* _right;//右孩子int _bf;//平衡因子AVLTreeNode<K, V>(const K& key, const V& value)//构造函数: _key(key), _value(value), _parent(NULL), _left(NULL), _right(NULL), _bf(0){}};
AVL树操作包括:插入,查找,删除等。
由于AVL树要求左右子树高度差的绝对值不超过1,因此AVL树必须通过旋转调平衡因子保持平衡。
插入:先插入节点再调平衡因子。
1、插入节点:
(1)若AVL树为空则new一个节点作为根节点;
(2)若要插入的节点等于根节点,返回false;
(3)若要插入的节点大于根节点,递归右子树插入节点,反之递归左子树插入节点。
2、调平衡因子(通过旋转)void _RotateL(Node*& parent) // '\' -> '/\'{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL){subRL->_parent = parent;}subR->_left = parent;subR->_parent = parent->_parent;Node* ppNode = parent->_parent;parent->_parent = subR;//更新节点信息if (ppNode == NULL){_root = subR;subR->_parent = NULL;}else if (ppNode->_left == parent){ppNode->_left = subR;}else{ppNode->_right = subR;}subR->_parent = ppNode;parent->_bf = subR->_bf = 0;//更新平衡因子}
void _RotateR(Node*& parent) // '/' -> '/\'{Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR){subLR->_parent = parent;}subL->_right = parent;subL->_parent = parent->_parent;Node* ppNode = parent->_parent;parent->_parent = subL;//更新节点信息if (ppNode == NULL){_root = subL;subL->_parent = NULL;}else if (ppNode->_left == parent){ppNode->_left = subL;}else{ppNode->_right = subL;}subL->_parent = ppNode;parent->_bf = subL->_bf = 0;//更新平衡因子}
查找:
1、若搜索树为空则返回空;
2、若要查找的节点等于根节点,返回根节点;
3、若要查找的节点大于根节点,递归查找右子树,反之递归查找左子树。
Node* Find(const K& key){if (_root == NULL){return NULL;}if (key > _root->_key){_root = _root->_right;}else if (key < _root->_key){_root = _root->_left;}else{return _root;}return NULL;}此外还有删除操作,先删除节点再调平衡因子。删除方法和搜索二叉树删除方法(http://blog.csdn.net/wanglelelihuanhuan/article/details/51585941)一样
完整代码如下:
AVLTree.h
#include<math.h>template<class K, class V>struct AVLTreeNode{K _key; //关键字V _value; AVLTreeNode<K, V>* _parent;//父亲AVLTreeNode<K, V>* _left;//左孩子AVLTreeNode<K, V>* _right;//右孩子int _bf;//平衡因子AVLTreeNode<K, V>(const K& key, const V& value)//构造函数: _key(key), _value(value), _parent(NULL), _left(NULL), _right(NULL), _bf(0){}};template<class K, class V>class AVLTree{typedef AVLTreeNode<K, V> Node;public:AVLTree():_root(NULL){}Node* Find(const K& key){if (_root == NULL){return NULL;}if (key > _root->_key){_root = _root->_right;}else if (key < _root->_key){_root = _root->_left;}else{return _root;}return NULL;}bool Insert(const K& key,const V& value){//先插入节点if (_root == NULL){_root = new Node(key, value);return true;}Node* parent = NULL;Node* cur = _root;while (cur){if (key > cur->_key){parent = cur;cur = cur->_right;}else if (key < cur->_key){parent = cur;cur = cur->_left;}else{return false;}}cur = new Node(key, value);if (key > parent->_key){parent->_right = cur;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}//再调平衡因子while (parent){if (parent->_left == cur){parent->_bf--;}else{parent->_bf++;}if (parent->_bf == 0) //已经是平衡树{break;}else if (parent->_bf == -1 || parent->_bf == 1) //继续回溯{cur = parent;parent = cur->_parent;}else // -2 2 调整 旋转{if (parent->_bf == 2){if (cur->_bf == 1) // '\' 左单旋 {_RotateL(parent);}else //-1 '>' 右左双旋{_RotateRL(parent);}}else //-2{if (cur->_bf == -1) // '/' 右单旋{_RotateR(parent);}else // '<' 左右双旋{_RotateLR(parent);}}break;}}return true;}void Inorder(){_Inorder(_root);cout << endl;}bool IsBalance(){return _IsBalance(_root);}protected:void _RotateL(Node*& parent) // '\' -> '/\'{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL){subRL->_parent = parent;}subR->_left = parent;subR->_parent = parent->_parent;Node* ppNode = parent->_parent;parent->_parent = subR;//更新节点信息if (ppNode == NULL){_root = subR;subR->_parent = NULL;}else if (ppNode->_left == parent){ppNode->_left = subR;}else{ppNode->_right = subR;}subR->_parent = ppNode;parent->_bf = subR->_bf = 0;//更新平衡因子}void _RotateR(Node*& parent) // '/' -> '/\'{Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR){subLR->_parent = parent;}subL->_right = parent;subL->_parent = parent->_parent;Node* ppNode = parent->_parent;parent->_parent = subL;//更新节点信息if (ppNode == NULL){_root = subL;subL->_parent = NULL;}else if (ppNode->_left == parent){ppNode->_left = subL;}else{ppNode->_right = subL;}subL->_parent = ppNode;parent->_bf = subL->_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){subL->_bf = -1;parent->_bf = 0;}else if (bf == -1){subL->_bf = 0;parent->_bf = 1;}else{subL->_bf = parent->_bf = 0;}subLR->_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){subR->_bf = 0;parent->_bf = -1;}else if (bf == -1){subR->_bf = 1;parent->_bf = 0;}else{subR->_bf = parent->_bf = 0;}subRL->_bf = 0;}int _Height(Node* root){if (root == NULL){return 0;}int Left = _Height(root->_left);int Right = _Height(root->_right);return (Left > Right ? Left:Right)+1;}void _Inorder(Node* root){if (root == NULL)return ;_Inorder(root->_left);cout << root->_key << " ";_Inorder(root->_right);}bool _IsBalance(Node*& root){if (root == NULL){return true;}int bf = _Height(root->_right) - _Height(root->_left) ;if (abs(bf) > 1 || bf != root->_bf){cout << "平衡因子有问题:" << root->_key << endl;return false;}return _IsBalance(root->_left) && _IsBalance(root->_right);}protected:Node* _root;};void TestInsert(){int arr1[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };AVLTree<int, int> alt1;for (int i = 0; i < sizeof(arr1) / sizeof(arr1[0]); ++i){alt1.Insert(arr1[i],i);}alt1.Inorder();cout << "isBlance? " << alt1.IsBalance() << endl;int arr[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16,14};AVLTree<int, int> alt2;for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i){alt2.Insert(arr[i], i);}alt2.Inorder();cout << "isBlance? " << alt2.IsBalance() << endl;}Test.cpp
#include<iostream>using namespace std;#include"AVLTree.h"int main(){TestInsert();return 0;}
3 0
- AVL树详解
- AVL树详解
- AVL树详解
- AVL树详解
- AVL树详解
- 【c++】AVL树详解
- 【数据结构】AVL树详解
- AVL树详解
- AVL树详解
- 平衡树(AVL)详解
- 平衡树(AVL)详解
- 平衡树详解之AVL
- 平衡二叉树AVL详解
- AVL树详解与总结
- AVL树平衡因子详解
- AVL平衡树(详解)-JAVA版本
- AVL平衡树(详解)-JAVA/C版本
- AVL树详解(附c++代码)
- js中disabled和readonly的区别
- 指针函数
- centos7.2 同时运行多个php-fpm主进程
- cocos2dx源码分析:shader的创建过程
- 类与类之间的关系
- AVL树详解
- linux nginx本机可以访问html,远程无法访问的解决办法
- cctype
- Linux 文件系统的目录结构
- Android使用GridView内容填充满不出现滚动的设计
- httpclient获取状态码(4.5.2版本)
- Hibernate中session的clear(),flush(),evict()方法详解
- 利用腾讯云学生套餐免费搭建wordpress博客
- ffmpeg的总体认识