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

最新网站查询大连甘井子区

最新网站查询,大连甘井子区,章丘网站建设哪家好,商城网站有免费建设的吗01. 初始AVL树 AVL树是最早发明的自平衡二叉搜索树。在AVL树中,任何节点的两个子树的高度差(平衡因子)最多为1,这使得AVL树能够保持较好的平衡性,从而保证查找、插入和删除操作的时间复杂度都是O(log n)。包含n个节点…

01. 初始AVL树

AVL树是最早发明的自平衡二叉搜索树。在AVL树中,任何节点的两个子树的高度差(平衡因子)最多为1,这使得AVL树能够保持较好的平衡性,从而保证查找、插入和删除操作的时间复杂度都是O(log n)。

在这里插入图片描述

包含n个节点的AVL树的高度始终保持在O(log n)


02. AVL树的结构

AVL 树在原 二叉搜索树 的基础上添加了 平衡因子 bf 以及用于快速向上调整的 父亲指针 parent,所以 AVL 树是一个三叉链结构。

在这里插入图片描述

2.1 AVL树节点定义

template <class K, class V>
struct AVLTreeNode // 定义借点类型
{AVLTreeNode(const std::pair<K, V> kv): _parent(nullptr), _left(nullptr), _right(nullptr), _kv(kv), _bf(0){}AVLTreeNode<K, V> *_parent;AVLTreeNode<K, V> *_left;AVLTreeNode<K, V> *_right;//这里并没有直接存储数据K,和V,而是像map那样将其封装成一个pair<K,V>类型。std::pair<K, V> _kv; // 存储键值对int _bf;             // 平衡因子
};

那么在AVLTree类方法实现只需创建一个AVLTreeNode<K,V>*类型的_root根节点。

规定: 当前实现的平衡因子,规定差值为 右 - 左,因此如果右子树增高,_bf++,左子树增高 _bf–,具体操作将在后面体现。


2.2 AVL树的方法

template<class K,class V>
class AVLTree{typedef TreeNode<K, V> Node;
public://插入bool insert(const pair<K, V> kv) {}//查找bool find(const K& kev) {}//中序遍历void order() {}void RotateR(Node* parent) {}	//右单旋void RotateL(Node* parent) {}	//左单旋void RRotateRL(Node* parent) {}	//右左双选void RotateLR(Node* parent) {}	//左右双选void order(Node* root) {}	//中序遍历private:Node* _root;
};

03. AVL树的插入

3.1插入过程

对于avl树的插入,实际是在二叉搜索树基础之上,增加了更新平衡因子和在这个过程中进行旋转调整的过程。

  1. 空树检查
    • 若树为空 (_root == nullptr),直接创建新节点作为根节点,返回 true
  2. 搜索插入位置
    • 从根节点开始比较 key
      • key < 当前节点:向左子树搜索
      • key > 当前节点:向右子树搜索
      • key == 当前节点:键已存在,返回 false
  3. 插入新节点
    • 创建新节点并链接到父节点:
      • key < 父节点:作为左孩子插入
      • key > 父节点:作为右孩子插入
  4. 平衡因子更新与调整(下面完成)
  • 更新平衡因子,然后判断是否需要进行旋转调整高度

bool Insert(const std::pair<K, V> kv){if (_root == nullptr){                         // 树中没有任何节点,直接new_root = new Node(kv); // 未使用Node(key, value),而是采用简直对的形式return true;}// 不为空树时的操作,找到插入点Node *parent = nullptr;Node *cur = _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==null)// 创建新节点插入cur = new Node(kv);if (kv.first < parent->_kv.first0){parent->_left = cur;cur->_parent = parent;}else{parent->_right = cur;cur->_parent = parent;}//控制平衡//1、更新平衡因子----更新新增节点到根节点的祖先路径//2、出现异常平衡因子,那么需要旋转平衡处理while (parent) {if (cur == parent->_right)parent->_bf++;elseparent->_bf--;if (parent->_bf == 0) {break;}else if (abs(parent->_bf) == 1) {//继续往上更新cur = parent;parent = parent->_parent;}else if (abs(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;}else {//说明插入更新平衡因子之前,树中平衡因子就有问题了assert(false);}} return true;}

3.1 左单旋

左单旋适用场景:

  P (_bf=+2)\							    C (_bf=0)C (_bf=+1)     调整为    		 /	   \\						     P       RR							  (_bf=0)

在这里插入图片描述

当插入10的时候出现不平衡。

左单旋:

  1. 确定parentsubRsubRL
  2. 使subRL成为parent右孩子
  3. subR左孩子变为parent
  4. 注意pparent的更新,和paarent为根节点情况
    void RotateL(Node *parent){ // parent在_bf=2处Node *subR = parent->_right;Node *subRL = subR->_left;// 先将subR的左孩子交给parentparent->_right = subRL;if (subRL != nullptr){subRL->_parent = parent;}Node *pparent = parent->_parent;//保存parent的父节点,确保更新平衡因子subR->_left = parent;parent->_parent = subR;if (_root == parent){//是否是根节点subR->_parent = nullptr;_root = subR;}else{if (pparent->_right == parent){pparent->_right = parent;}else{pparent->_left = subR;}subR->_parent = pparent;}parent->_bf = subR->_bf = 0;}
注意事项
  1. 空指针检查
    • subRL 可能为 nullptr,需判断后再操作其父指针
  2. 根节点更新
    • parent 是根节点,旋转后需更新 _root 指向 subR
  3. 平衡因子重置
    • 左单旋后,parentsubR 的平衡因子必为 0

3.2 右单旋

          P (_bf=-2)/						   C (_bf=0)C (_bf=-1)				 /	   \/						L	   PL (_bf=0)					  (_bf=-0)

在这里插入图片描述

当插入10的时候出现不平衡。

右单旋:

  1. 确定parentsubLsubLR
  2. 使subLR成为parent左孩子
  3. subR右孩子变为parent
  4. 注意pparent的更新,和paarent为根节点情况
//右单旋
void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;//先将 subL 的右孩子移交给父亲parent->_left = subLR;if (subLR != nullptr)subLR->_parent = parent;Node* pparent = parent->_parent;subL->_right = parent;parent->_parent = subL;//再将父亲移交给 subL,subL 成为新父亲if (parent == _root){//如果原父亲为根,那么此时需要更新 根subL->_parent = nullptr;_root = subL;}else{//单纯改变链接关系if (pparent->_right == parent)pparent->_right = subL;elsepparent->_left = subL;subL->_parent = pparent;}//更新平衡因子parent->_bf = subL->_bf = 0;
}
注意事项
  1. 空指针检查
    • subLR 可能为 nullptr,需判断后再操作其父指针。
  2. 根节点更新
    • parent 是根节点,旋转后需更新 _root 指向 subL
  3. 平衡因子重置
    • 右单旋后,parentsubL 的平衡因子必为 0

3.3 右左单旋

在这里插入图片描述

//右左双旋
void RotateRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int BF = subRL->_bf;//先右单旋RotateR(subR);//再左单旋RotateL(parent);//根据不同的情况更新平衡因子if(BF == 0){parent->_bf = subR->_bf = 0;}else if (BF == 1){parent->_bf = -1;subR->_bf = 0;subRL->_bf = 0;}else if (BF == -1){parent->_bf = 0;subR->_bf = 1;subRL->_bf = 0;}else{//非法情况std::cerr << "此处的平衡因子出现异常!" << std::endl;assert(false);	//直接断言报错}
}

右左单旋:

  1. 右单旋:
    1. 确定 parentsubRsubRL
    2. subRL的右子树变为 subR左子树,parent右子树为subRL左子树
    3. subRL向上提
平衡因子调整(分三类)
情况subRL->_bf调整后平衡因子触发条件
情况10parent = subR = subRL = 0新节点是 subRL 自身
情况2-1parent = 0, subR = +1, subRL = 0新节点在 subRL 左子树
情况3+1parent = -1, subR = 0, subRL = 0新节点在 subRL 右子树

3.4 左右双旋

右左双旋左右双旋逻辑非常像,这里就不演示了,直接看代码实现:

//左右双旋
void RotateLR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;int BF = subLR->_bf;//先左单旋RotateL(subL);//再右单旋RotateR(parent);//根据不同的情况更新平衡因子if (BF == 0){parent->_bf = subL->_bf = 0;}else if (BF == 1){parent->_bf = 0;subL->_bf = -1;subLR->_bf = 0;}else if (BF == -1){parent->_bf = 1;subL->_bf = 0;subLR->_bf = 0;}else{//非法情况std::cerr << "此处的平衡因子出现异常!" << std::endl;assert(false);	//直接断言报错}
}

3.5 AVL查找

	//查找bool find(const K& kv) {Node* ptail = _root;while (ptail){if (kv.first > ptail->_kv->first){ptail = ptail->_right;}else if (kv.first < ptail->_kv->first){ptail = ptail->_left;}else{return true;}}return false;}


文章转载自:

http://T2Y3xVIC.mhsmj.cn
http://d78ODE6D.mhsmj.cn
http://5cmTIieU.mhsmj.cn
http://R0lDWavO.mhsmj.cn
http://bsje3Qg5.mhsmj.cn
http://tZNidLef.mhsmj.cn
http://VE7jBcwA.mhsmj.cn
http://iiXzZFPQ.mhsmj.cn
http://jPsMjLUQ.mhsmj.cn
http://a6PEBOQQ.mhsmj.cn
http://YhIP8u0X.mhsmj.cn
http://DxE7dNCV.mhsmj.cn
http://FlYCnvBq.mhsmj.cn
http://A441MIIL.mhsmj.cn
http://f0HQEnxR.mhsmj.cn
http://EB15ctJ7.mhsmj.cn
http://UBZL5HSX.mhsmj.cn
http://dTbVHlXv.mhsmj.cn
http://DvQUsIA6.mhsmj.cn
http://XLXLE99t.mhsmj.cn
http://10ufQfoV.mhsmj.cn
http://c2d4jkLE.mhsmj.cn
http://Mp7wkLo1.mhsmj.cn
http://gISa7XkR.mhsmj.cn
http://2UaHlUvR.mhsmj.cn
http://lmhe6MUz.mhsmj.cn
http://TyqC5zdM.mhsmj.cn
http://9UILDNHq.mhsmj.cn
http://ibN35odv.mhsmj.cn
http://HD4Hx22G.mhsmj.cn
http://www.dtcms.com/wzjs/689501.html

相关文章:

  • 伊利网站建设水平评价在线购物网站设计
  • 网站域名跳转是怎么做的招聘模板制作app
  • 株洲网站建设企业pageadmin安装教程
  • 朝阳区网站建设君和广州海珠建网站
  • 最好的科技资讯网站银川网站建设报价
  • 校园网站建设价格后台网站建设招聘
  • 哈尔滨网站关键字优化电子商务专业就业前景如何
  • 建设银行吴中支行网站工厂关键词网络推广
  • 珠海网站建设咨询seo排名软件哪个好
  • 建设一个广告联盟的网站网站建设费可以计入办公费用么
  • 太原制作公司网站seo关键词排名工具
  • 虚拟主机网站建设步骤?wordpress商城主题
  • 网站开发的技术内容wordpress页面文字的样式
  • 网站优化方案哪里做网站一套一百
  • 优秀的网站建设给个做的网站吗
  • 好的网站收入wordpress拼图
  • 优秀企业网站设计要点淘宝关键词优化
  • 优化网站排名的方法代码优化
  • 宜春集团网站建设网络登录认证
  • 济南海绵城市建设官方网站收录软件最多的网站
  • 门户网站需要哪些人怎么做下载网站
  • 网站开发流程怎么写河南移动官网网站建设
  • 网站后台从哪里进去厦门响应式网站
  • 动漫网站建设答辩ppt北京房产交易网官网
  • 英文电商网站建设仿网站视频教程
  • 如何让商家建设网站免费ppt模板软件
  • 网站建设的认识深圳网站建设方案书
  • 我想做网站seo优化推广
  • 最大的网站建设公司wordpress改写rewrite
  • 高端设计网站桂林北京网站建设