做企业网站的前景,香包怎么做制作方法,虚拟主机 两个网站,沭阳做网站的公司AVL树 一.概念二.插入1.搜索二叉树2.平衡因子 三.旋转1.更新平衡因子2.旋转1.左单旋2.右单旋3.先右旋再左旋4.先左旋再右旋 四.完整代码 一.概念 二叉搜索树虽可以缩短查找的效率#xff0c;但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元… AVL树 一.概念二.插入1.搜索二叉树2.平衡因子 三.旋转1.更新平衡因子2.旋转1.左单旋2.右单旋3.先右旋再左旋4.先左旋再右旋 四.完整代码 一.概念 二叉搜索树虽可以缩短查找的效率但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素效率低下。因此两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整)即可降低树的高度从而减少平均搜索长度。 二.插入
AVL树就是在二叉搜索树的基础上引入了平衡因子因此AVL树也可以看成是二叉搜索树。那么AVL树的插入过程可以分为两步
按照二叉搜索树的方式插入新节点调整节点的平衡因子
1.搜索二叉树 2.平衡因子 一颗树如何插入会影响节点的平衡因子呢平衡因子是右节点减去左节点 如果我们插在6的左边那么6的平衡因子减一同理7的左子树高度加一那么7的平衡因子减一再继续向上5的右子树的最高高度并没有发生改变所以5的平衡因子不发生改变。 同理插在6的右边6的平衡因子加一7的平衡因子减一。 如果插在9的右边那么8的平衡因子就会变为2说明此树不平衡。 总结 1.新镇在左parent平衡因子减减。 2.新增在右parent平衡因子加加。 3.如果更新后的parent平衡因子为0说明parent所在的树的高度不变不会再影响祖先不用再继续更新了。 4如果更新后parent的平衡因子为1或者-1那么就需要继续向上更新。 5.如果更新后parent平衡因子为2或-2说明该树不平衡对parent所在的子树进行旋转。 三.旋转
1.更新平衡因子 由上面分析可以知道更新结束的条件是平衡因子为0或者更新到根节点。 首先在每个节点里加入平衡因子 接着在插入的同时更新平衡因子 2.旋转 旋转要保持的要求 1.旋转后也是搜索二叉树。 2.变成平衡树并且降低树的高度。 如果在一棵原本是平衡的AVL树中插入一个新节点可能造成不平衡此时必须调整树的结构使之平衡化。根据节点插入位置的不同AVL树的旋转分为四种
1.左单旋 通过观察我们可以发现我们其实只需要移动蓝色的节点就可以实现左旋。我们将这三个节点分别记录然后修改它们的内部属性即可。 2.右单旋 3.先右旋再左旋 这里的旋转并不难直接复用就可以.
困难的部分是如何调控平衡因子插入的位置不同平衡因子也不同分三种情况讨论。 4.先左旋再右旋
同理左右旋与上文一样需要分三种情况来讨论。 四.完整代码
测试
#includeKVL.h
#includevectorint main()
{AVLTreeint,int t;srand(time(0));vectorinta;for (int i 0; i 100; i)a.push_back(rand());for (auto x : a)t.Insert(make_pair(x,x));t.Print();
}树
#includeiostream
#includeassert.h
using namespace std;templateclass K,class V
struct KVLTreeNode
{pairK, V_kv;KVLTreeNodeK, V* _left;KVLTreeNodeK, V* _right;KVLTreeNodeK, V* _parent;int _bf;//平衡因子KVLTreeNode(const pairK,Vkv):_kv(kv),_left(nullptr),_right(nullptr),_parent(nullptr),_bf(0){}
};templateclass K,class V
class AVLTree
{
public:typedef KVLTreeNodeK,V Node;bool Insert(const pairK, V kv){if (_root nullptr){_root new Node(kv);return true;}Node* cur _root;Node* parent _root;while (cur){if (kv.first cur-_kv.first){parent cur;cur cur-_left;}else if (kv.first cur-_kv.first){parent cur;cur cur-_right;}elsereturn false;}cur new Node(kv);if (kv.first parent-_kv.first){parent-_left cur;cur-_parent parent;}else{parent-_right cur;cur-_parent parent;}//控制平衡while (parent){if (cur parent-_left){parent-_bf--;}else // if (cur parent-_right){parent-_bf;}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){// 子树不平衡了需要左旋转if (parent-_bf 2 cur-_bf 1){RotateL(parent);}//右旋转else if (parent-_bf -2 cur-_bf -1){RotateR(parent);}//先左单旋再右旋转else if (parent-_bf -2 cur-_bf 1){RotateLR(parent);}//先右单选再左单旋else if (parent-_bf 2 cur-_bf -1){RotateRL(parent);}break;}else{assert(false);}}return true;}void RotateL(Node* parent){Node* cur parent-_right;Node* curleft cur-_left;Node* ppnode parent-_parent;//记录父节点的父节点//父节点的右孩子变成curleftparent-_right curleft;if(curleft)//细节注意curleft为空时不能操作curleft-_parent parent;//父节点变为cur的左孩子cur-_left parent;parent-_parent cur;//如果原来父节点是根节点if (parent _root){_root cur;cur-_parent nullptr;}else//如果不是根节点判断它应该是左儿子还是右儿子{if (ppnode-_left parent){ppnode-_left cur;}else{ppnode-_right cur;}cur-_parent ppnode;}parent-_bf cur-_bf 0;}void RotateR(Node* parent){Node* cur parent-_left;Node* curright cur-_right;Node* pphead parent-_parent;//父节点到cur右边cur-_rightparent;parent-_parent cur;//父节点的左孩子变成currightparent-_left curright;if (curright)curright-_parent parent;//cur的父节点变为原来父节点的父节点if (pphead)//如果不是根节点{if (pphead-_left parent)pphead-_left cur;elsepphead-_right cur;cur-_parent pphead;}else{_root cur;cur-_parent nullptr;}parent-_bf cur-_bf 0;}void RotateRL(Node* parent){Node* cur parent-_right;Node* curleft cur-_left;int bf curleft-_bf;RotateR(parent-_right);RotateL(parent);//第一种情况if (bf 0){parent-_bf cur-_bf 0;}//第二种情况else if (bf 1){parent-_bf -1, cur-_bf 0, curleft-_bf 0;}//第三种情况else if(bf-1){cur-_bf 1, curleft-_bf 0, parent-_bf 0;}//其他情况错误else{assert(false);}}void RotateLR(Node* parent){Node* cur parent-_left;Node* curright cur-_right;int bf curright-_bf;RotateL(parent-_left);RotateR(parent);if (bf 0){parent-_bf cur-_bf 0;}else if (bf 1){parent-_bf curright-_bf 0, cur-_bf -1;}else if (bf -1){parent-_bf 1, cur-_bf curright-_bf 0;}else{assert(false);}}void Print(){Print(_root);}void Print(Node* root){if (root nullptr) return;Print(root-_left);cout root-_kv.second ;Print(root-_right);}
private:Node* _rootnullptr;
};