AVL树的实现
来源:互联网 发布:安倍 知乎 编辑:程序博客网 时间:2024/06/08 09:29
AVL树又名高度平衡的搜索二叉树,上一篇文章我们讲到二叉搜索树时,说到它存在一个问题:退化,这使得它的时间复杂度从O(lgN)降到了O(N)。为了解决这个问题,出现了一棵新的树,也就是AVLtree,我们先来看看它的性质:
1,它是一棵搜索 二叉树,所以满足每个节点的值大于左子树中任意节点的值,并且小于右子树中任意节点的值。
2,它是一棵平衡树,他要求每个节点的左右子树的深度之差不能超过1,即这棵树的倒数第二层节点是满的。
3,每一棵子树都是一棵AVL树;
4,每个节点都有一个平衡因子bf,取值为-1、0、1 。它的值等于右子树的深度减去左子树的深度。
AVL树节点的结构如下:
template<class K,class V>struct AVLTreeNode{ AVLTreeNode<K,V>* _left; AVLTreeNode<K,V>* _right; AVLTreeNode<K,V>* _parent; K _key; V _value; int _bf; //平衡因子 AVLTreeNode(const K& key,const V& value) :_left(NULL),_right(NULL),_parent(NULL),_key(key),_value(value),_bf(0) {}};
对于AVL树的操作,这里主要讲解一下插入
插入操作中,通过对平衡因子的判定来进行相应的旋转操作来改变树的结构。整个过程可以分为三个过程:1,寻找插入位置;2,插入;3,调整(重点也是难点)。对此我画了个流程图,如下:
代码如下:
bool Insert(const K& key,const V& value) { if (_root == NULL) { _root = new Node(key, value); return true; } Node* cur = _root; Node* parent = cur; 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); cur->_parent = parent; if (parent->_key > key) parent->_left = cur; else parent->_right = cur; //调整平衡因子 while (parent) { if (cur == parent->_left) parent->_bf--; else parent->_bf++; if (parent->_bf == 0) { break; } else if (parent->_bf == 1 || parent->_bf == -1) { cur = parent; parent = cur->_parent; } else // parent->_bf == 2 / == -2 { //旋转 if (parent->_bf == 2) { if (cur->_bf == 1) { RotateL(parent); } else { RotateRL(parent); } } else { if (cur->_bf == 1) { RotateLR(parent); } else { RotateR(parent); } } break; } } return true; }
下面我们再一次来看一下四种旋转(LL, LR, RR, RL):
1,对于LL,在左旋之后,只需将该节点(parent)和右孩子根节点(subR)的平衡因子置为0即可。
代码如下:
void RotateL(Node* parent) { Node* subR = parent->_right; Node* subRL = subR->_left; parent->_right = subRL; if (subRL) subRL->_parent = parent; subR->_left = parent; Node* pparent = parent->_parent; if (pparent) { parent->_parent = subR; if (pparent->_left == parent) pparent->_left = subR; else pparent->_right = subR; } else _root = subR; subR->_parent = pparent; subR->_bf = parent->_bf = 0; }
2,对于RR,在右旋之后,只需将该节点(parent)和左孩子根节点(subL)的平衡因子置为0即可。
代码如下:
void RotateR(Node* parent) { Node* subL = parent->_left; Node* subLR = subL->_right; parent->_left = subLR; if (subLR) subLR->_parent = parent; subL->_right = parent; Node* pparent = parent->_parent; if (pparent) { parent->_parent = subL; if (pparent->_left == parent) pparent->_left = subL; else pparent->_right = subL; } else _root = subL; subL->_parent = pparent; subL->_bf = parent->_bf = 0; }
3,对于LR,保存subLR的平衡因子,用于后面判断:如果为1,subRL的右孩子会补为parent的左孩子,subL的右节点无人补,是空,subL的bf置为-1,如果为-1,subLR的左孩子会补为subL的右孩子,而parent的左节点无人补,parent的bf置为1
代码如下:
void RotateLR(Node* parent) { Node* subL = parent->_left; Node* subLR = parent->_right; int bf = subLR->_bf; RotateL(parent->_left); RotateR(parent); if (bf == 1) { subL->_bf = -1; } else if (bf == -1) { parent->_bf = 1; } subLR->_bf = 0; }
4,对于RL,保存subRL的平衡因子,用于后面判断:如果为1,subRL的右孩子会补为subR的左孩子,parent的右节点无人补,是空,parent的bf置为-1,如果为-1,subRL的左孩子会补为parent的右孩子,而subR的左节点无人补,subR的bf置为1
代码如下:
void RotateRL(Node* parent) //先旋转,后调整平衡因子 { Node* subR = parent->_right; Node* subRL = subR->_left; int bf = subRL->_bf; RotateR(parent->_right); RotateL(parent); if (1 == bf) //subRL的右孩子会补为subR的左孩子,parent的右节点无人补,是空,bf置为-1 { parent->_bf = -1; } else if (-1 == bf) //subRL的左孩子会补为parent的右孩子,而subR的左节点无人补,bf置为1 { subR->_bf = 1; } subRL->_bf = 0; }
这样AVL树的插入就解决了,我们需要一个函数来判定该树是否是AVL树。这个简单,只需遍历整棵树,看他的平衡因子是否正确即可。代码如下:
bool IsBalance() { int depth = 0; return _IsBalance(_root, depth); } bool _IsBalance(Node* root, int& depth) { if (root == NULL) { depth = 0; return true; } int leftDepth = 0; int rightDepth = 0; if (_IsBalance(root->_left, leftDepth) == false) return false; if (_IsBalance(root->_right, rightDepth) == false) return false; if ((rightDepth - leftDepth) != root->_bf) { cout << "bf 异常" << root->_key << endl; //return false; } depth = rightDepth > leftDepth ? rightDepth + 1 : leftDepth + 1; return abs(rightDepth - leftDepth) < 2; }
像查找,求深度等这种问题的解决就不具体讲解了,后面附有完整代码。
完整代码
#include<iostream>using namespace std;template<class K,class V>struct AVLTreeNode{ AVLTreeNode<K,V>* _left; AVLTreeNode<K,V>* _right; AVLTreeNode<K,V>* _parent; K _key; V _value; int _bf; //平衡因子 AVLTreeNode(const K& key,const V& value) :_left(NULL),_right(NULL),_parent(NULL),_key(key),_value(value),_bf(0) {}};template<class K,class V>class AVLTree{ typedef AVLTreeNode<K,V> Node;public: AVLTree() :_root(NULL) {} ~AVLTree() { _Delete(_root); } bool Insert(const K& key,const V& value) { if (_root == NULL) { _root = new Node(key, value); return true; } Node* cur = _root; Node* parent = cur; 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); cur->_parent = parent; if (parent->_key > key) parent->_left = cur; else parent->_right = cur; //调整平衡因子 while (parent) { if (cur == parent->_left) parent->_bf--; else parent->_bf++; if (parent->_bf == 0) { break; } else if (parent->_bf == 1 || parent->_bf == -1) { cur = parent; parent = cur->_parent; } else // parent->_bf == 2 / == -2 { //旋转 if (parent->_bf == 2) { if (cur->_bf == 1) { RotateL(parent); } else { RotateRL(parent); } } else { if (cur->_bf == 1) { RotateLR(parent); } else { RotateR(parent); } } break; } } return true; } void InOrder() { _InOrder(_root); cout << endl; } Node* Find(const K& x) { return _Find(x); } bool IsBalance() { int depth = 0; return _IsBalance(_root, depth); }protected: bool _IsBalance(Node* root, int& depth) //注意:depth引用 { if (root == NULL) { depth = 0; return true; } int leftDepth = 0; int rightDepth = 0; if (_IsBalance(root->_left, leftDepth) == false) return false; if (_IsBalance(root->_right, rightDepth) == false) return false; if ((rightDepth - leftDepth) != root->_bf) { cout << "bf 异常" << root->_key << endl; //return false; } depth = rightDepth > leftDepth ? rightDepth + 1 : leftDepth + 1; return abs(rightDepth - leftDepth) < 2; } Node* _Find(Node* root, const K& x) { while (root) { if (x > root->_key) root = root->_right; else if (x < root->_key) root = root->_key; else return root; } return NULL; } void _InOrder(Node* root) { if (root == NULL) return; _InOrder(root->_left); cout << root->_key << " "; _InOrder(root->_right); } void _Delete(Node*& root) { if (root == NULL) return; _Delete(root->_left); _Delete(root->_right); delete root; root = NULL; } int Depth(Node* root) { if (root == NULL) return 0; int leftDepth = Depth(root->_left); int rightDepth = Depth(root->_right); return leftDepth > rightDepth ?leftDepth + 1 : rightDepth + 1; } void RotateL(Node* parent) { Node* subR = parent->_right; Node* subRL = subR->_left; parent->_right = subRL; if (subRL) subRL->_parent = parent; subR->_left = parent; Node* pparent = parent->_parent; if (pparent) { parent->_parent = subR; if (pparent->_left == parent) pparent->_left = subR; else pparent->_right = subR; } else _root = subR; subR->_parent = pparent; subR->_bf = parent->_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; Node* pparent = parent->_parent; if (pparent) { parent->_parent = subL; if (pparent->_left == parent) pparent->_left = subL; else pparent->_right = subL; } else _root = subL; subL->_parent = pparent; subL->_bf = parent->_bf = 0; } void RotateLR(Node* parent) { Node* subL = parent->_left; Node* subLR = parent->_right; int bf = subLR->_bf; RotateL(parent->_left); RotateR(parent); if (bf == 1) { parent->_bf = 0; subL->_bf = -1; } 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 (1 == bf) { subR->_bf = 0; parent->_bf = -1; } else if (-1 == bf) { parent->_bf = 0; subR->_bf = 1; } else { parent->_bf = subR->_bf = 0; } subRL->_bf = 0; }private: Node* _root;};void Test(){ AVLTree<int, int> t; //int a[] = {16, 3, 7, 11, 9, 26, 18, 14, 15}; int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 }; for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i) { t.Insert(a[i], i); cout << a[i] << "IsBalance?" << t.IsBalance() << endl; } t.InOrder(); cout << "IsBalance?" << t.IsBalance() << endl;}
- AVL树的实现
- AVL树的实现
- AVL树的实现
- AVL 树的实现
- AVL树的实现
- AVL树的实现
- AVL树的实现
- AVL树的实现
- AVL树的实现
- AVL树的实现
- AVL树的实现
- AVL树的实现
- AVL树的实现
- AVL树的实现
- AVL树的实现
- AVL树的实现
- AVL树的实现
- AVL树的实现
- 干货:分分钟干掉 Bug 之灵活地运用 Findbugs 过滤器
- http://www.cnblogs.com/yuqianwen/p/4285686.html
- Win10 JAVA环境变量配置
- 欢迎使用CSDN-markdown编辑器
- NDK常用命令
- AVL树的实现
- Effective c++ 学习笔记(三)
- 多重继承以及多重继承中二义性的解决:虚基类
- P1351 联合权值 noip提高组2014
- JAVA 多线程读取大文件 基金每日增量报送
- 22. OP-TEE中TA与CA执行流程-------tee-supplicant(一)
- HashSet的add方法的问题
- [java]代码块
- iOS10推送必看