您好,欢迎访问一九零五行业门户网

代码详解AVL树的插入

avl树被称为高度平衡的二叉搜索树,尽量降低二叉树的高度,来保持二叉树的平衡,减少树的平均搜索长度。
avl树的性质:1、左子树和右子树的高度之差(绝对值)不超过1
                        2、树中的每棵子树都是avl树,
                        3、每个节点都有一个平衡因子,取值为(-1,0,1),通过平衡因子来判断树的平衡。
avl树的插入需要考虑以下的几种情况:(箭头表示要插入的方向和节点)
第一种情况:插入的节点在20的右边,但是这样导致10的平衡因子大于1所以需要进行旋转才能改变平衡因子
第二种情况:在左边插入,导致平衡因子也不满足条件,需要旋转
第三种情况:插入的节点可能不构成单旋,所以需要双旋来解决
第四种情况:与第三种情况相反的双旋
如此通过旋转就可以达到在插入的时候让此二叉树达到平衡。
实现代码如下:
//main函数 #define _crt_secure_no_warnings 1 #include<iostream> #include<assert.h> using namespace std; #include"avltree.h" int main() { testavltree(); system("pause"); return 0; }
//avltree ----> 被称为高度平衡的二叉搜索树 //使用三叉链来实现此二叉平衡搜索树 //性质:左右高度差不超过1 && 该树的左右子树都为二叉平衡树 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) {} //使用非递归的插入 bool insert(const k& key, const v& value) { //如果根节点不存在说明插入的节点是第一个节点,直接new 一个即可 if (_root == null){ _root = new node(key, value); return true; } node* cur = _root; node* parent = null; while (cur) { if (cur->_key < key){ parent = cur; cur = cur->_right; } else if (cur->_key>key){ parent = cur; cur = cur->_left; } else{ return false; } } //走到这里,说明这个节点不存在,先new cur = new node(key, value); //比较插入节点的值与父节点的值,再考虑链上左还是右 if (parent->_key < key){ parent->_right = cur; cur->_parent = parent; } else if (parent->_key>key){ parent->_left = cur; cur->_parent = parent; } else{ while (parent) { //判断cur是插在了parent的左边还是右边,再判断平衡因子是++还是-- if (cur == parent->_left){ parent->_bf--; } else{ parent->_bf++; } //++或--之后,判断平衡因子是否等于2或等于-2 if (parent->_bf == 0) //等于0说明没有变,则跳出循环 { break; } else if (parent->_bf == 1 || parent->_bf == -1) { cur = parent; parent = cur->_parent; } else if (parent->_bf == 2 || parent->_bf == -2)//如果等于2或者等于-2则不再插入,先调节为二叉平衡树再插入 { //根据平衡因子来判断需要调整的树是哪种类型,再选择单旋还是双旋 //如果父节点的平衡因子等于2,说明右子树比左子树高,再判断右子树的子树是在它的左边还是右边 if (parent->_bf == 2) { if (cur->_bf == 1){ rotatel(parent); } else{ rotaterl(parent); } } else { if (cur->_bf == -1) rotater(parent); else rotatelr(parent); } } } } return true; } //cur = parent; //右单旋 void rotater(node* parent) { //需要记录parent上面是否还有父亲节点 node* ppnode = parent->_parent; node* subl = parent->_left; node* sublr = subl->_right; parent->_left = sublr; //如果sublr存在 就将它的父亲置为parent if (sublr) sublr->_parent = parent; subl->_right = parent; parent->_parent = subl; //如果parent等于根节点,说明已经到第一个节点,不需要调整,直接将subl作为根即可 if (parent == _root) { _root = subl; subl->_parent = null; } else //如果还没有到根节点还需要判断parent是左还是右 { if (ppnode->_left == parent) ppnode->_left = subl; else{ ppnode->_right = subl; } subl->_parent = ppnode; } } //左单旋 void rotatel(node* parent) { node* ppnode = parent->_parent; node* subr = parent->_right; node* subrl = subr->_left; parent->_right = subrl; //判断subrl是否存在 if (subrl){ subrl->_parent = parent; } subr->_left = parent; parent->_parent = subrl; if (_root == parent) { _root = subr; subr->_parent = null; } else { if (ppnode->_left == parent) ppnode->_left = subr; else ppnode->_right = subr; subr->_parent = ppnode; } } //左右单旋 void rotatelr(node* parent) { rotatel(parent->_right); rotater(parent); } //右左单旋 void rotaterl(node* parent) { rotater(parent->_left); rotatel(parent); } void inorder() { _inorder(_root); cout << endl; } void _inorder(node* root) { if (root == null) return; _inorder(root->_left); cout << root->_key << " "; _inorder(root->_right); } bool isbalance() { return _isbalance(_root); } bool _isbalance(node* root) { if (root == null) return; int leftheight = _height(root->_left); int rightheight = _height(root->_right); return abs(rightheight - leftheight) < 2 && _isbalance(root->_left) && _isbalance(root->_right); } size_t _height(node* root) { if (root == null) return 0; size_t left = _height(root->_left); size_t right = _height(root->_right); return left > right ? left + 1 : right + 1; } private: node* _root; }; void testavltree() { avltree<int, int> t; int a[] = { 16,3,7,11,9,26,18,14,15}; for (int i = 0; i < (sizeof(a) / sizeof(a[0])); i++) { cout<<t.insert(a[i], 0)<<endl; } t.inorder(); }
以上就是代码详解avl树的插入的详细内容。
其它类似信息

推荐信息