二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。
我们采用三叉链的方式来实现AVL首先我们定义的AVLTreeNode节点如下所示:
templatestruct AVLTreeNode { AVLTreeNode * _left; AVLTreeNode * _right; AVLTreeNode * _parent; int _bf; pair _kv; AVLTreeNode(const pair & kv) :_left(nullptr), _right(nullptr), _parent(nullptr), _bf(0), _kv(kv) { } };
首先对于AVL树来说,我们这里实现AVLTree的插入实现:当AVL树插入数据时,可以分为以下四种情况 右单旋、左单旋、右左单旋、左右单旋,为了方便记忆我们可以将左、右单旋看成一条直线、右左和左右单旋看成折线。如下所示:
程序实现:
#include#include using namespace std; template struct AVLTreeNode { AVLTreeNode * _left; AVLTreeNode * _right; AVLTreeNode * _parent; int _bf; pair _kv; AVLTreeNode(const pair & kv) :_left(nullptr), _right(nullptr), _parent(nullptr), _bf(0), _kv(kv) { } }; template class AVLTree { typedef AVLTreeNode Node; public: AVLTree():_root(nullptr) { } void _Destory(Node* root) { if (root == nullptr) return; _Destory(root->_left); _Destory(root->_right); delete root; } ~AVLTree() { _Destory(_root); _root = nullptr; } void _InOrder(Node* root) { if (root == nullptr) return; _InOrder(root->_left); cout << root->_kv.first << " "; _InOrder(root->_right); } void InOrder() { _InOrder(_root); cout << endl; } bool Insert(const pair & kv) { if (_root == nullptr) { _root = new Node(kv); return true; } Node* parent = _root; Node* cur = _root; while (cur) { if (kv.first > cur->_kv.first) { parent = cur; cur = cur->_right; } else if (kv.first < cur->_kv.first) { parent = cur; cur = cur->_left; } else { return false; } } cur = new Node(kv); if (parent->_kv.first>kv.first) { parent->_left = cur; } else { parent->_right = cur; } cur->_parent = parent; //开始平衡因子的检测 到这从插入的节点往上对平衡因子进行更新 while (cur != _root) { if (parent->_right == cur) { parent->_bf++; } else { parent->_bf--; } //对更新完后的父亲节点进行检测 分为三种情况 //1、如果parent节点的_bf为0 则跳出 //2、如果parent节点的平衡因子为1或者-1则继续向上更新 //3、如果Parent的节点的平衡因子为-2或者2则不平衡了,应该旋转了 if (parent->_bf == 0) { break; } else if (parent->_bf == 1 || parent->_bf == -1) { cur = parent; parent = parent->_parent; } else if (parent->_bf == 2 || parent->_bf == -2) { //这里开始旋转保持AVLTree的平衡 //旋转分为四种情况 //1、 右单旋 //2、右左单旋 //3、左单旋 //4、左右单旋 //首先要进行右单选时,那么parent->bf==-2时进行右旋 if (parent->_bf == -2) { if (cur->_bf == -1) { //这里是右单旋 RotateR(parent); } else //cur->bf==1 左右双旋转 { RotateLR(parent); } } else //cur->bf==2 { if (cur->_bf == 1) { RotateL(parent); } else { RotateRL(parent); } } break; } } return true; } void RotateR(Node* parent) { Node* SubL = parent->_left; Node* SubLR = SubL->_right; parent->_left = SubLR; if (SubLR) { SubLR->_parent = parent; } Node* Parentparent = parent->_parent; SubL->_right = parent; parent->_parent = SubL; if (parent == _root) { _root = SubL; _root->_parent = nullptr; } else { if (Parentparent->_left == parent) { Parentparent->_left = SubL; } else { Parentparent->_right = SubL; } SubL->_parent = Parentparent; } SubL->_bf = parent->_bf = 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* Parentparent = parent->_parent; if (parent == _root) { _root = SubR; SubR->_parent = nullptr; } else { if (Parentparent->_left == parent) { Parentparent->_left = SubR; } else { Parentparent->_right = SubR; } SubR->_parent = Parentparent; } parent->_bf = SubR->_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; SubLR->_bf = 0; } else if (bf == -1) { SubL->_bf = 0; parent->_bf = 1; SubLR->_bf = 0; } else { SubL->_bf = 0; parent->_bf = 0; SubLR->_bf = 0; } } void RotateRL(Node* parent) { Node* SubR = parent->_right; Node* SubRL = SubR->_left; int bf = SubR->_bf; RotateR(parent->_right); RotateL(parent); if (bf == 1) { SubR->_bf = 0; SubRL->_bf = 0; parent->_bf = -1; } else if (bf == -1) { parent->_bf = 0; SubR->_bf = 1; SubRL->_bf = 0; } else { parent->_bf = 0; SubR->_bf = 0; SubRL->_bf = 0; } } Node* Find(const K& key) { Node* cur = _root; while (cur) { if (cur->_kv.first < key) { cur = cur->_right; } else if (cur->_kv.first > key) { cur = cur->_left; } else { return cur; } } return nullptr; } int IsHeight(Node* root) { if (root == nullptr) return 0; int Left=IsHeight(root->_left); int Right=IsHeight(root->_right); return Left > Right ? Left + 1 : Right + 1; } bool _IsBalance(Node* root) { int left = IsHeight(root->_left); int right = IsHeight(root->_right); return abs(left - right) < 2; } bool IsAVLTree() { return _IsBalance(_root); } private: Node* _root; };
#include"AVLTree.h" using namespace std; void Test_AVLTree() { //int a[] = { 1, 3, 5, 7, 6 }; //int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 }; //int a[] = { 6,7,8,9,10}; int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 }; AVLTreet; for (auto e : a) { t.Insert(make_pair(e,e)); } t.InOrder(); } int main() { Test_AVLTree(); return 0; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)