这两天研究了一下AVL树,所以准备浅谈一下AVL树。
记得上次的博客中说到了二叉所搜树,也说到了他还说一种有欠缺的二叉树,当输入单调递增或单调递减的数据后,他会退化成链表,这样会严重影响效率,所以AVL树就被引出来了,下面就开始简单介绍AVL树吧。
首先AVL树是一种严格的平衡二叉树,他要求所有节点所在的二叉树都满足一个条件:平衡因子不大于2,搜索二叉树也就接近满二叉树了,这个时候搜索的效率就比较高了,但是它也因此付出了很高的代价,那就是他会不断的旋转,下面我们就开始AVL树的旋转吧!
我们来分析AVL树不平衡的时候旋转的情况吧,我总结了一下,大概如下几种情况吧:
以上就是几种情况的分析,为什么在左右双旋的时候或者右左双旋的时候我要画出两种插入节点的位置呢?不是无聊,而是在双旋的时候插入位置对平衡因子有影响,这个问题在单旋中是不存在的,下面就来看看吧:
1.右左单旋
也就是上面第三幅图,我们可以推理得出:
(1).当插入节点10的时候,10最终会被分配到左子树中,具体位置是在8右边,节点
(2).当插入节点13的时候
右左单旋和这个刚好对称,情况相似,所以就不举例说明了,下面给出代码吧,代码针对AVL树插入节点的四种情况进行了分析:
#pragma once #include <iostream> using namespace std; template<class K,class V> struct AVLTreeNode { typedef AVLTreeNode<K, V> Node; AVLTreeNode<K, V> *_left; AVLTreeNode<K, V> *_right; AVLTreeNode<K, V> *_parent; K _key; V _val; int _bf; AVLTreeNode(const K &key = K(), const V &val = V()) : _key(key) , _val(val) , _bf(0) , _left(NULL) , _right(NULL) , _parent(NULL) {} }; template<class K,class V> class AVLTree { typedef AVLTreeNode<K, V> Node; public: AVLTree() : _root(NULL) {} bool Insert(const K key, const V val) { if (_root == NULL) { _root = new Node(key, val); return true; } Node* parent = NULL; Node* cur = _root; while (cur) { parent = cur; if (key > cur->_key) { cur = cur->_right; } else if (key < cur->_key) { cur = cur->_left; } else { return false; } } cur = new Node(key, val); cur->_parent = parent; if (key < parent->_key) { parent->_left = cur; } else { parent->_right = cur; } while (parent) { if (parent->_left == cur) { --parent->_bf; } else { ++parent->_bf; } if (parent->_bf == 0) { //平衡 return true; } else if (abs(parent->_bf) < 2) { //继续上调 cur = parent; parent = parent->_parent; } else { //不平衡,分四种情况讨论 if (cur->_bf > 0 && parent->_bf > 0) { //情况1 左单旋 _RotateL(parent, cur); return true; } else if (parent->_bf < 0 && cur < 0) { //情况2 右单旋 _RotateR(parent, cur); return true; } else if (parent->_bf < 0 && cur->_bf > 0) { //情况3 左右单旋 Node* pSubL = parent->_left; Node* pSubLR = pSubL->_right; int bf = pSubLR->_bf; // bf = -1 , 0 , 1 产生的影响 _RotateL(pSubL, pSubLR); _RotateR(parent, pSubLR); //此处千万不要传递(parent,parent->_left)因为两者都是parent的引用 if (bf == -1) { // //cur->_bf = 0; parent->_bf = 1; } else if (bf == 1) { cur->_bf = -1; //parent->_bf = 0; } else {} return true; } else //parent->_bf > 0 && cur->_bf < 0 { //情况4 右左单旋 Node* pSubR = parent->_right; Node* pSubRL = pSubR->_left; int bf = pSubRL->_bf; // bf = -1 , 0 , 1 产生不同的影响 _RotateR(pSubR, pSubRL); _RotateL(parent, pSubRL); if (bf == -1) { cur->_bf = 1; //parent->_bf = 0; } else if (bf == 1) { parent->_bf = -1; //cur->_bf = 0; } else {} return true; } } } } bool Isbalance() { return _Isbalance(_root); } int Height(Node* root) { return _Height(root); } ~AVLTree() { //_Destroy(); } protected: int _Height(Node *root) { if (root == NULL) return 0; int left = 1 + _Height(root->_left); int right = 1 + _Height(root->_right); return left > right ? left : right; } bool _Isbalance(Node *root) { if (root == NULL) { return true; } int bf = _Height(root->_right) - _Height(root->_left); if ( root->_bf != bf ) { cout << "is unbalance:" << root->_key << endl; return false; } return _Isbalance(root->_left); return _Isbalance(root->_right); } void _RotateL(Node*& parent,Node*& cur) { cur->_parent = parent->_parent; if (parent->_parent) { //parent 还有父节点 if (parent == parent->_parent->_left) parent->_parent->_left = cur; else parent->_parent->_right = cur; } else { //parent为根节点 _root = cur; } parent->_parent = cur; if (cur->_left) cur->_left->_parent = parent; parent->_right = cur->_left; cur->_left = parent; //平衡因子置为 0 parent->_bf = 0; cur->_bf = 0; } void _RotateR(Node*& parent, Node*& cur) { cur->_parent = parent->_parent; if (parent->_parent) { //parent 还有父节点 if (parent == parent->_parent->_left) parent->_parent->_left = cur; else parent->_parent->_right = cur; } else { //parent为根节点 _root = cur; } //Node* pNode = cur; parent->_parent = cur; if (cur->_right != NULL) cur->_right->_parent = parent; parent->_left = cur->_right; //pNode->_right = parent; cur->_right = parent; //平衡因子 parent->_bf = 0; cur->_bf = 0; } void _RotateLR() {} void _RotateRL() {} protected: Node *_root; }; void TestAVLTree() { AVLTree<int, int> At; //At.Insert(10, 1); //At.Insert(15, 1); //At.Insert(20, 1); //At.Insert(8, 1); //At.Insert(12, 1); ////左右双旋 ////At.Insert(13, 1); //影响平衡因子 ////At.Insert(11, 1); //影响平衡因子 /************************************************/ At.Insert(10, 1); At.Insert(15, 1); At.Insert(20, 1); At.Insert(18,1); At.Insert(25, 1); //右左双旋 //At.Insert(17, 1); //影响平衡因子 //At.Insert(19, 1); //影响平衡因子 At.Isbalance(); }