当前位置: 首页 > news >正文

网站pv uv统计wordpress 破解主题下载地址

网站pv uv统计,wordpress 破解主题下载地址,php精品网站建设,网站建设职业情况AVL树是一种遵循严格左右对称的搜索二叉树,它左右子树的高度差不超过1,这样就可以避免搜索二叉树可能出现的单边子树过长带来的时间复杂度不理想的问题,达到搜索树原本理想的n(logn)。为了左右子树的平衡,它引入了平衡因子这个概念…

AVL树是一种遵循严格左右对称的搜索二叉树,它左右子树的高度差不超过1,这样就可以避免搜索二叉树可能出现的单边子树过长带来的时间复杂度不理想的问题,达到搜索树原本理想的n(logn)。为了左右子树的平衡,它引入了平衡因子这个概念,每个结点都有⼀个平衡因⼦,任一结点的平衡因⼦等于右子树的高度减去左子树的高度,也就是说任何结点的平衡因⼦等于0/1/-1,AVL树并不是必须要平衡因⼦,但是有了平衡因⼦可以更⽅便我们去进⾏观察和控制树是否平衡。

接下来实现一下它的整体结构:

//.h
template<class K, class V>
struct AVLTreeNode
{
// 需要parent指针,后续更新平衡因⼦可以看到pair<K, V> _kv;//用来存储键值对数据,与整体结构没太大关系,不用太关注AVLTreeNode<K, V>* _left;AVLTreeNode<K, V>* _right;AVLTreeNode<K, V>* _parent;int _bf; // 平衡因子AVLTreeNode(const pair<K, V>& kv):_kv(kv), _left(nullptr), _right(nullptr), _parent(nullptr),_bf(0){}
};
template<class K, class V>
class AVLTree
{typedef AVLTreeNode<K, V> Node;
public:bool Insert(const pair<K, V>& kv){//...}
private:Node* _root = nullptr;
};

接下来就开始实现着重关注的插入函数:

思路:1.完成插入步骤,数据的插入和搜索二叉树的插入一样,小了往左走,大了往右,找到末尾后再让新节点cur与parent比较决定插在左边还是右边。

bool Insert(const pair<K, V>& kv)
{if (_root == nullptr){_root = new Node(kv);return true;} Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;} else if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;} else{return false;}}cur = new Node(kv);if (parent->_kv.first < kv.first){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;//...
}

2.更新平衡因子。因为平衡因子=右子树的高度-左子树的高度,所以插在左边,parent的平衡因子就--,在右边就++。当然,插入也有可能会影响到parent往上的那些节点,也要更新。为什么是有可能呢?因为如果parent的一边正好是空的,cur插入的是那个刚好的空位,那么上面那些节点的左右子树高度就没变化,不用往上更新了,总结一下就是当cur和parent的平衡因子更新完为0就结束更新,否则继续往上更新上面节点的平衡因子。

3.处理不平衡情况。插入可能会导致平衡因子超出-1到1的范围,这意味着左右子树高度差变为2,需要旋转来调整。现在先展示代码,接下来详细解释。

	//第一步的代码// 2.更新平衡因⼦while (parent){// 更新平衡因⼦if (cur == parent->_left)parent->_bf--;elseparent->_bf++;if (parent->_bf == 0){// 更新结束break;}else if (parent->_bf == 1 || parent->_bf == -1){// 继续往上更新cur = parent;parent = parent->_parent;}// 3.不平衡了,旋转处理else if (parent->_bf == 2 || parent->_bf == -2){if (parent->_bf == -2 && cur->_bf == -1){RotateR(parent);//右单旋}else if (parent->_bf == 2 && cur->_bf == 1){RotateL(parent);//左单旋}else if (parent->_bf == -2 && cur->_bf == 1){RotateLR(parent);//左右双旋}else if (parent->_bf == 2 && cur->_bf == -1){RotateRL(parent);//右左双旋}else{assert(false);}break;}//预防不是-1,0,1和2,-2的未知情况else{assert(false);}}

插入后导致高度差为2或-2的有4种情况,由于大树是由一个个小树组成,接下来的示例图抽象成一个模型来解释具体到图形是怎样的,对应四种旋转方式:

第一种:右单旋

对应的是parent的左子树比较高,cur也是左子树较高的情况,用平衡因子来表现就是parent平衡因子为-2,cur为parent的左子树且平衡因子为-1。插入位置在cur的左子树。

右单旋就是让cur的右子树(subLR)向右旋转作为parent的的左子树,再让修改后的parent作为cur的右子树,这里为了方便理解位置,subL就是cur,subLR就是cur的右子树,具体如下图:

(没绘图软件的VIP,导出不给去水印 T-T)

整体思路就是这样,直接看代码(这里比较容易忘记修改cur的_parent,记得在parent的_parent被修改之前记录一下)

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;// parent有可能是整棵树的根,也可能是局部的⼦树// 如果是整棵树的根,要修改_root// 如果是局部的指针要跟上⼀层链接if (parentParent == nullptr){_root = subL;subL->_parent = nullptr;}else{if (parent == parentParent->_left){parentParent->_left = subL;}else{parentParent->_right = subL;}subL->_parent = parentParent;}parent->_bf = subL->_bf = 0;
}

第二种:左单旋

对应的是parent的右子树比较高,cur也是右子树较高的情况,用平衡因子来表现就是parent平衡因子为2,cur为parent的右子树且平衡因子为1。插入位置在cur的右子树。整体思路和右单旋类似,让cur的左子树向左旋转作为parent的的右子树,再让修改后的parent作为cur的左子树。图,代码如下:

void RotateL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;Node* parentParent = parent->_parent;subR->_left = parent;parent->_parent = subR;if (parentParent == nullptr){_root = subR;subR->_parent = nullptr;} else{if (parent == parentParent->_left){parentParent->_left = subR;} else{parentParent->_right = subR;} subR->_parent = parentParent;} parent->_bf = subR->_bf = 0;
}

第三种:左右双旋

对应的是parent的左子树比较高,cur右子树较高的情况,用平衡因子来表答就是parent平衡因子为-2,cur为parent的左子树且平衡因子为1。由于这种情况需要经过两次旋转,所以要细分一下,插入位置有三种可能,在cur的右节点的左子树或右子树还有cur左为空,插入位置为右的情况。

下面用图演示是怎么旋转的:

(其实从整体来理解就是把b给subL,c给parent,然后subLR做根,subL和parent分别作为它的左右子树)

对应代码:

void RotateLR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RotateL(parent->_left);RotateR(parent);//更新平衡因子if (bf == 0)//第三种情况{subL->_bf = 0;subLR->_bf = 0;parent->_bf = 0;} else if (bf == -1)//第一种情况{subL->_bf = 0;subLR->_bf = 0;parent->_bf = 1;} else if (bf == 1)//第二种情况{subL->_bf = -1;subLR->_bf = 0;parent->_bf = 0;} else{assert(false);}
}

第四种:右左双旋

对应的是parent的右子树比较高,cur左子树较高的情况,用平衡因子来表达就是parent平衡因子为2,cur为parent的左子树且平衡因子为-1。同样需要经过两次旋转,先右旋再左旋,插入位置有三种可能,在cur的左节点的左子树或右子树还有cur右为空,插入位置为左的情况。

思路和左右双旋类似:

(从整体来理解就是把b给subR,c给parent,然后subRL做根,parent和subR分别作为它的左右子树)

代码如下:

void RotateRL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);//更新平衡因子if (bf == 0)//第三种情况{subR->_bf = 0;subRL->_bf = 0;parent->_bf = 0;} else if (bf == 1)//第一种情况{subR->_bf = 0;subRL->_bf = 0;parent->_bf = -1;} else if (bf == -1)//第二种情况{subR->_bf = 1;subRL->_bf = 0;parent->_bf = 0;} else{assert(false);}
}

http://www.dtcms.com/a/473934.html

相关文章:

  • 全参数与PEFT深度剖析
  • 记忆翻牌游戏
  • 自己做的网站如何让别人访问织梦帝国wordpress
  • Linux -程序地址空间
  • (Spring)@PathVariable 与 @RequestParam 区别与应用
  • SpringAI从入门到精通 (2)
  • Linux 12mybash的实现
  • K8s YAML 文件详解:从语法到实战编写指南
  • 社区版Idea怎么创建Spring Boot项目?Selected Java version 17 is not supported. 问题解决
  • 益阳市 网站建设电子商务网站建设的主要风险
  • SpringBootRemotePowershellAdmin:开箱即用的 Windows远程运维开源工具
  • 插槽vue/react
  • 对vue生命周期的理解
  • 2017民非单位年检那个网站做黄山旅游攻略景点必去
  • [笔记 自用]CAN总线通信配置
  • HTML 教程
  • 用自己服务器做网站用备案怎样在亚马逊网上开店
  • PHP操作elasticsearch7.8
  • 学校网站建设需求分析哪个小说网站可以做封面
  • 网站制作类软件推荐莆田网站格在哪里做
  • TypeScript 面试题及详细答案 100题 (21-30)-- 接口(Interface)
  • 承德网站新手怎么做网络推广
  • 6. 从0到上线:.NET 8 + ML.NET LTR 智能类目匹配实战--渐进式学习闭环:从反馈到再训练
  • 2.c++面向对象(五)
  • python中的一些运算符
  • 【嵌入式面试题】boss收集的11道,持续更新中
  • 保证样式稿高度还原
  • 网站建设 源码怎么注册公司名
  • [xboard] 34 buildroot 的overlay机制
  • 某公司站点的挖掘实战分享