AVL平衡树的旋转
2017-05-25 23:43
381 查看
AVL树是一种平衡查找树(每个节点左子树与右子树的高度差不超过1),这样可以保证树不偏向一边,使查找的时间复杂度降低。
需要给节点一个平衡因子_bf(右子树的高度减去左子树的高度)。
AVL树的插入分为下面几种情况:
在父节点的右子树插入节点,父节点的bf+1,如果父节点bf等于0,树平衡,插入成功,父节点bf等于1,右子树高度加1,接着向上调整。
在父节点的左子树插入节点,父节点的bf-1,如果父节点bf等于0,树平衡,插入成功,父节点bf等于-1,左子树高度加1,接着向上调整。
如果父节点的bf为2或者-2,树不平衡,进行旋转。
在较高右子树的右边插入节点需要进行左旋转。
pCur为插入节点,parent的bf为2,这时候把SubR提高,parent降低,重新满足平衡条件。
如果原右子树SubR的左子树SubRL不为空,SubR的左子树需要指向parent,所以把SubRL连到parent的右子树上。重新满足平衡。
–》
左单旋与右单旋为镜像,旋转方法相同,介绍省略。。
当父节点的bf为2,右子树的bf为-1,用上面方法没法一次旋转完成。(在较高右子树的左侧插入节点使进行右左双旋)。
先对SubR进行右单旋。
最后平衡
左右双旋为右左双旋的镜像,省略。。
代码实现:
需要给节点一个平衡因子_bf(右子树的高度减去左子树的高度)。
AVL树的插入分为下面几种情况:
在父节点的右子树插入节点,父节点的bf+1,如果父节点bf等于0,树平衡,插入成功,父节点bf等于1,右子树高度加1,接着向上调整。
在父节点的左子树插入节点,父节点的bf-1,如果父节点bf等于0,树平衡,插入成功,父节点bf等于-1,左子树高度加1,接着向上调整。
如果父节点的bf为2或者-2,树不平衡,进行旋转。
在较高右子树的右边插入节点需要进行左旋转。
pCur为插入节点,parent的bf为2,这时候把SubR提高,parent降低,重新满足平衡条件。
如果原右子树SubR的左子树SubRL不为空,SubR的左子树需要指向parent,所以把SubRL连到parent的右子树上。重新满足平衡。
–》
左单旋与右单旋为镜像,旋转方法相同,介绍省略。。
当父节点的bf为2,右子树的bf为-1,用上面方法没法一次旋转完成。(在较高右子树的左侧插入节点使进行右左双旋)。
先对SubR进行右单旋。
最后平衡
左右双旋为右左双旋的镜像,省略。。
代码实现:
#include <iostream> using namespace std; #include <assert.h> #include <stdlib.h> template <class K, class V> struct AVLTreeNode { AVLTreeNode(const K& key = K(), const V& value = V()) :_key(key) , _value(value) , _pLeft(NULL) , _pRight(NULL) , _parent(NULL) , _bf(0) {} AVLTreeNode *_pLeft; AVLTreeNode *_pRight; AVLTreeNode *_parent; K _key; V _value; int _bf; }; template <class K, class V> class AVLTree { typedef AVLTreeNode<K, V> Node; public: AVLTree() :_pRoot(NULL) {} bool Insert(const K& key, const V& value) { if (NULL == _pRoot) { _pRoot = new Node(key, value); return true; } Node *pCur = _pRoot; Node *parent = NULL; while (pCur) { if (key < pCur->_key) { parent = pCur; pCur = pCur->_pLeft; } else if (key > pCur->_key) { parent = pCur; pCur = pCur->_pRight; } else return false; } pCur = new Node(key, value); if (key < parent->_key) { parent->_pLeft = pCur; --parent->_bf; } else { parent->_pRight = pCur; ++parent->_bf; } pCur->_parent = parent; while (parent && parent->_bf != 0) { if (parent->_bf == 2) { if (pCur->_bf == 1) _RotateL(parent); else _RotateRL(parent); return true; } else if (parent->_bf == -2) { if (pCur->_bf == -1) _RotateR(parent); else _RotateLR(parent); return true; } if (parent->_bf == 1) { pCur = parent; parent = parent->_parent; if (parent) ++parent->_bf; else return true; } else if (parent->_bf == -1) { pCur = parent; parent = parent->_parent; if (parent) --parent->_bf; else return true; } } } bool IsBalance() { return IsBalanceTree(_pRoot); } void InOrder() { cout << "中序:"; _InOrder(_pRoot); cout << "end" << endl; } private: void _RotateL(Node* parent) { Node *SubR = parent->_pRight; Node *SubRL = SubR->_pLeft; parent->_pRight = SubRL; if (SubRL != NULL) SubRL->_parent = parent; Node *pPParent = parent->_parent; parent->_parent = SubR; SubR->_pLeft = parent; SubR->_parent = pPParent; if (NULL == pPParent) _pRoot = SubR; else if (pPParent->_pLeft == parent) { pPParent->_pLeft = SubR; } else { pPParent->_pRight = SubR; } SubR->_bf = 0; parent->_bf = 0; } void _RotateR(Node* parent) { Node *SubL = parent->_pLeft; Node *SubLR = SubL->_pRight; parent->_pLeft = SubLR; if (SubLR != NULL) SubLR->_parent = parent; Node *pPParent = parent->_parent; parent->_parent = SubL; SubL->_pRight = parent; SubL->_parent = pPParent; if (NULL == pPParent) _pRoot = SubL; else if (pPParent->_pLeft == parent) { pPParent->_pLeft = SubL; } else { pPParent->_pRight = SubL; } SubL->_bf = 0; parent->_bf = 0; } void _RotateRL(Node *parent) { _RotateR(parent->_pRight); _RotateL(parent); parent->_pRight->_bf = -1; } void _RotateLR(Node *parent) { _RotateL(parent->_pLeft); _RotateR(parent); parent->_pLeft->_bf = 1; } void _InOrder(Node *proot) { if (NULL == proot) return; _InOrder(proot->_pLeft); cout << proot->_value << " "; _InOrder(proot->_pRight); } int Hight(Node *proot) { if (NULL == proot) return 0; if (proot->_pLeft == NULL && proot->_pRight == NULL) return 1; int LeftHight = Hight(proot->_pLeft); int RightHight = Hight(proot->_pRight); return 1 + ((LeftHight > RightHight) ? LeftHight : RightHight); } bool IsBalanceTree(Node *proot) { if (NULL == proot) return true; if (proot->_bf >= 2 || proot->_bf <= -2) { cout << proot->_key<<"平衡因子大于2!" << endl; return false; } if (Hight(proot->_pRight) - Hight(proot->_pLeft) != proot->_bf) { cout <<proot->_key<<" 平衡因子不正确!" << endl; return false; } if (IsBalanceTree(proot->_pLeft) && IsBalanceTree(proot->_pRight)) return true; } private: Node *_pRoot; }; int main() { int arr[] = { 1,2,3,4,5,6,7,8,9,10 }; AVLTree<int, int> avtree; for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i) { avtree.Insert(arr[i], arr[i]); avtree.IsBalance(); } avtree.InOrder(); getchar(); return 0; }
相关文章推荐
- (PAT)1123.[平衡树旋转] Is It a Complete AVL Tree
- 平衡树(AVL)详解
- 数据结构实验:AVL平衡树做出用户登录系统(dos界面)
- 【数据结构】【平衡树】无旋转treap
- 【学校OJ】 avl平衡树+线段树 二逼平衡树
- 【Treap】[BZOJ 3224]Tyvj 1728 普通平衡树 & 非旋转实现
- 平衡二叉树AVL - 插入节点后旋转方法分析
- avl 平衡搜索二叉树的旋转图示
- [BZOJ3224]普通平衡树(旋转treap,STL-vector)
- AVL 平衡二叉树旋转方法
- AVL 树的插入、删除、旋转归纳
- AVL 平衡树
- C#平衡树(AVLTree)
- [置顶] AVL旋转图及其代码的实现
- AVL的旋转
- 编程练习——平衡树(AVLTree)
- 【jzoj4678】【钱仓】【平衡树】【avl】【队列】
- 二查平衡树的插入与删除(四种旋转)
- AVL Tree概念之旋转
- AVL(平衡)树的旋转