石油网页设计与网站建设深圳燃气公司网上营业厅

web/2025/9/27 21:37:09/文章来源:
石油网页设计与网站建设,深圳燃气公司网上营业厅,网站建设 深度网,网页设计师培训学费文章目录 为什么要有AVL树什么是AVL树AVL树的实现元素的插入平衡因子的更新AVL树的旋转 AVL树的检查完整实现 本篇总结的是AVL树中的全部内容#xff0c;配有详细的图解过程 为什么要有AVL树 前面对map/multimap/set/multiset进行了简单的介绍#xff0c;在其文档介绍中发现… 文章目录 为什么要有AVL树什么是AVL树AVL树的实现元素的插入平衡因子的更新AVL树的旋转 AVL树的检查完整实现 本篇总结的是AVL树中的全部内容配有详细的图解过程 为什么要有AVL树 前面对map/multimap/set/multiset进行了简单的介绍在其文档介绍中发现这几个容器有个共同点是其底层都是按照二叉搜索树来实现的但是二叉搜索树有其自身的缺陷假如往树中插入的元素有序或者接近有序二叉搜索树就会退化成单支树时间复杂度会退化成O(N)因此map、set等关联式容器的底层结构是对二叉树进行了平衡处理即采用平衡树来实现 什么是AVL树 当一个二叉搜索树形如下面的场景时进行查找的时候效率会相当低下 甚至当接近为单支树的时候查找效率会相当于在顺序表中的查找效率因此俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis发明了一个解决方案当向二叉搜索树中插入新结点后如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整)即可降低树的高度从而减少平均搜索长度这也就是AVL树的由来 一棵AVL树或者是空树或者是具有以下性质的二叉搜索树 它的左右子树都是AVL树左右子树高度之差的绝对值不超过1 左右子树的高度差也叫做平衡因子在这样的树中进行搜索时间复杂度是O(logN) AVL树的实现 元素的插入 首先定义出节点由于AVL树对于向上寻找信息有需求因此在定义节点信息的时候要有该节点指向父亲的指针 // 定义AVL树的节点 templateclass K, class V struct AVLTreeNode {AVLTreeNode(const pairK, V kv):_left(nullptr), _right(nullptr), _parent(nullptr), _kv(val), bf(0){}// 左子树指针 右子树指针 父亲节点指针 节点值 平衡因子AVLTreeNodeK, V* _left;AVLTreeNodeK, V* _right;AVLTreeNodeK, V* _parent;pairK, V _kv;int bf; };下面定义AVL树的插入AVL树的插入主要是先插入到一个二叉搜索树中再对于二叉搜索树进行平衡因此要先插入到二叉搜索树 bool Insert(const pairK, V kv) {Node* newnode new Node(kv);if (_root nullptr){_root newnode;return true;}Node* cur _root;Node* parent nullptr;while (cur){if (newnode-_kv.first cur-_kv.first){parent cur;cur cur-_left;}else if (newnode-_kv.first cur-_kv.first){parent cur;cur cur-_right;}else{return false;}}if (newnode-_kv.first parent-_kv.first){parent-_right newnode;cur-_parent parent;}else{parent-_left newnode;cur-_parent parent;} }上面就是二叉搜索树的基本部分下面开始的是AVL树平衡问题 平衡因子的更新 新节点插入后AVL树的平衡性可能会遭到破坏引入平衡因子的意义也就在于此因此插入后的第一步是要更新平衡因子看有没有遭到破坏对于平衡因子的调整有下面的几种情况 如果插入到节点的左侧平衡因子-1即可如果插入到节点的右侧平衡因子1即可 节点插入后会有新的问题看下面的场景 依据这个原理可以写出代码来更新平衡因子 // 节点的插入// 节点插入的逻辑和搜索树基本一致只是如果不符合要求需要进行旋转bool Insert(const pairK, V kv){Node* newnode new Node(kv);if (_root nullptr){_root newnode;return true;}Node* cur _root;Node* parent nullptr;while (cur){if (newnode-_kv.first cur-_kv.first){parent cur;cur cur-_left;}else if (newnode-_kv.first cur-_kv.first){parent cur;cur cur-_right;}else{return false;}}if (newnode-_kv.first parent-_kv.first){parent-_right newnode;cur-_parent parent;}else{parent-_left newnode;cur-_parent parent;}// 上面就是二叉搜索树的基本部分下面更新平衡因子while (parent){// 如果cur是parent的左节点平衡因子-1如果是右节点平衡因子1if (cur parent-_left){parent-_bf--;}else{parent-_bf;}// 判断父节点平衡因子绝对值的情况// 1. 如果为0则证明不需要向上更新// 2. 如果为1则需要向上更新// 3. 如果为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){// 开始进行旋转}else{// 如果绝对值比2大说明平衡因子出错了强制结束assert(false);}}}AVL树的旋转 那当上面的情况已经发生AVL树应该如何进行平衡这就引入了旋转的概念 在AVL树中当破坏了AVL树的平衡后总共有四种会引发的旋转 1. 新节点插入较高左子树的左侧引发右单旋 因此下面实现右单旋的代码实现 // 右单旋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 (_root parent){_root subL;subL-_parent nullptr;}else{if (parentParent-_left parent){parentParent-_left subL;}else{parentParent-_right subL;}subL-_parent parentParent;}subL-_bf parent-_bf 0;} 2. 新节点插入在较高右子树的右侧引发左单旋 // 左单旋void RotateL(Node* parent){Node* subR parent-_right;Node* subRL subR-_left;Node* parentParent parent-_parent;// 更新节点parent-_right subRL;parent-_parent subR;subR-_left parent;subR-_parent parentParent;if (subRL)subRL-_parent parent;// 更新parentParentif (_root parent){_root subR;}else{if (parentParent-_left parent){parentParent-_left subR;}else{parentParent-_right subR;}}parent-_bf subR-_bf 0;} 3. 新节点插入较高右子树的左侧引发先右单旋再左单旋 对于这种情况来说总共有下面的两种情况 代码实现也有了思路先左单旋再右单旋最后修改平衡因子的值即可而修改平衡因子的值可以通过subRL的bf值来判断不同的情况根据不同的情况修改不同的值即可 // 先右单旋再左单旋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 0;subR-_bf 1;subRL-_bf 0;}else if (bf 1){// 在右子树进行的插入subRL-_bf 0;subR-_bf 0;parent-_bf -1;}else{assert(false);}} 4. 新节点插入较高左子树的右侧引发先左单旋再右单旋 分析方法和前面类似 // 先进行左单旋再进行右单旋void RotateLR(Node* parent){Node* subL parent-_left;Node* subLR subL-_right;int bf subLR-_bf;RotateL(subL);RotateR(parent);// 更换平衡因子if (bf 0){subL-_bf subLR-_bf 0;}else if (bf 1){// 插入在右子树subL-_bf -1;subLR-_bf 0;parent-_bf 0;}else if (bf -1){// 插入在左子树parent-_bf 1;subL-_bf 0;subLR-_bf 0;}else{assert(false);}} AVL树的检查 依据上面的实现可以基本实现AVL树那如何验证AVL树是否正确其实验证也很简单只需要看每个节点的平衡因子是否等于对应的右子树减左子树的值即可 // 用于检查树的高度int TreeHeight(Node* root){if (root nullptr)return 0;int leftheight TreeHeight(root-_left);int rightheight TreeHeight(root-_right);return max(leftheight, rightheight) 1;}// 保持树的封装 进行检查AVL树bool IsBalance(){return _IsBalance(root);}// 进行检查AVL树bool _IsBalance(Node* root){if (root nullptr)return true;int leftheight TreeHeight(root-_left);int rightheight TreeHeight(root-_right);if (rightheight - leftheight ! root-_bf)return false;return abs(rightheight-leftheight)2 _IsBalance(root-_left) _IsBalance(root-_right);}这样就完成了AVL树的测试 完整实现 #include iostream #include assert.h using namespace std;// 定义AVL树的节点 templateclass K, class V struct AVLTreeNode {AVLTreeNode(const pairK, V kv):_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), _bf(0){}// 左子树指针 右子树指针 父亲节点指针 节点值 平衡因子AVLTreeNodeK, V* _left;AVLTreeNodeK, V* _right;AVLTreeNodeK, V* _parent;pairK, V _kv;int _bf; };// 定义AVL树 templateclass K, class V class AVLTree {typedef AVLTreeNodeK, V Node; public:AVLTree():_root(nullptr){}// 节点的插入// 节点插入的逻辑和搜索树基本一致只是如果不符合要求需要进行旋转bool Insert(const pairK, V kv){if (_root nullptr){_root new Node(kv);return true;}Node* cur _root;Node* parent nullptr;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 (kv.first parent-_kv.first){parent-_right cur;cur-_parent parent;}else{parent-_left cur;cur-_parent parent;}// 上面就是二叉搜索树的基本部分下面更新平衡因子while (parent){// 如果cur是parent的左节点平衡因子-1如果是右节点平衡因子1if (cur parent-_left){parent-_bf--;}else{parent-_bf;}// 判断父节点平衡因子绝对值的情况// 1. 如果为0则证明不需要向上更新// 2. 如果为1则需要向上更新// 3. 如果为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){// 开始进行旋转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){RotateRL(parent);}else if (parent-_bf -2 cur-_bf 1){RotateLR(parent);}break;}else{// 如果绝对值比2大说明平衡因子出错了强制结束assert(false);}}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 (_root parent){_root subL;subL-_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;Node* parentParent parent-_parent;// 更新节点parent-_right subRL;parent-_parent subR;subR-_left parent;subR-_parent parentParent;if (subRL)subRL-_parent parent;// 更新parentParentif (_root parent){_root subR;}else{if (parentParent-_left parent){parentParent-_left subR;}else{parentParent-_right subR;}}parent-_bf subR-_bf 0;}// 先右单旋再左单旋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 0;subR-_bf 1;subRL-_bf 0;}else if (bf 1){// 在右子树进行的插入subRL-_bf 0;subR-_bf 0;parent-_bf -1;}else{assert(false);}}// 先进行左单旋再进行右单旋void RotateLR(Node* parent){Node* subL parent-_left;Node* subLR subL-_right;int bf subLR-_bf;RotateL(subL);RotateR(parent);// 更换平衡因子if (bf 0){subL-_bf subLR-_bf 0;}else if (bf 1){// 插入在右子树subL-_bf -1;subLR-_bf 0;parent-_bf 0;}else if (bf -1){// 插入在左子树parent-_bf 1;subL-_bf 0;subLR-_bf 0;}else{assert(false);}}// 用于检查树的高度int TreeHeight(Node* root){if (root nullptr)return 0;int leftheight TreeHeight(root-_left);int rightheight TreeHeight(root-_right);return max(leftheight, rightheight) 1;}// 保持树的封装 进行检查AVL树bool IsBalance(){return _IsBalance(root);}// 进行检查AVL树bool _IsBalance(Node* root){if (root nullptr)return true;int leftheight TreeHeight(root-_left);int rightheight TreeHeight(root-_right);if (rightheight - leftheight ! root-_bf)return false;return abs(rightheight-leftheight)2 _IsBalance(root-_left) _IsBalance(root-_right);}private:Node* _root; };

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/82984.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

做网站网页的公司行业网站建设的开发方案

PLC_博图系列☞FB&FC 文章目录 PLC_博图系列☞FB&FC背景介绍FB&FC与C 类比博图中定义函数块 (FB)函数 (FC) 关键字: PLC、 西门子、 博图、 FC 、 FB 背景介绍 这是一篇关于PLC编程的文章,特别是关于西门子的博图软件。我并不是专业的P…

企业电子商务网站建设总结wordpress 中文主题网

在现代科技的迅猛发展下,直播系统源码平台被开发搭建出来,为人们的生活方式带来了很大的改变,直播系统源码平台的好友、短视频、直播、社区等功能让很多人越来越热衷于去在平台上刷视频、看直播、分享生活。用户的喜爱也督促了直播系统源码平…

深圳龙华做网站的互联网创业有哪些项目可以做

背景 今天在安装jenkins后,使用java运行war包的时候,提示jdk1.8版本太低,需要提高版本,所以就需要切换jdk版本 解决 在用户变量中,首先更改了JAVA_HOME的地址为17的目录,发现javac的版本改为17了&#x…

华为建站php编程软件

我们知道,继承,组合,重载,重写是java语言的面向对象实现的基本特征。 那么在java内部,究竟是如何实现这些面对对象的基本特征的呢?继承和组合是面向对象中代码复用的主要实现方式,他们可以达到类…

济南做网站公司xywlcnWordPress的手机菜单键

博主18年的互联网软件开发经验,从一名程序员小白逐步成为了一名架构师,我想通过平台将经验分享给大家,因此博主每天会在各个大牛网站点赞量超高的博客等寻找该技术栈的资料结合自己的经验,晚上进行用心精简、整理、总结、定稿&…

商城类网站方案昆山市建设监察大队官方网站

往期回顾 【QT入门】Qt自定义控件与样式设计之自定义QLineEdit实现搜索编辑框-CSDN博客 【QT入门】Qt自定义控件与样式设计之自定义QTabWidget实现tab在左,文本水平的效果-CSDN博客【QT进阶】Qt Web混合编程之CEF、QCefView简单介绍-CSDN博客 【QT进阶】Qt Web混合编…

重庆省建设厅网站网站备案账号是什么

DBSCAN聚类算法学习笔记 一些概念名词 MinPts:聚类在一起的点的最小数目,超过这一阈值才算是一个族群 核心点:邻域内数据点超过MinPts的点 边界点:落在核心点邻域内的点称为边界点 噪声点:既不是核心点也不是边界点的…

站外推广免费网站自己做网站用什么软件下载

前言:使用Unity开发的游戏需要支持泰语本地化,以及解决显示泰语时Unity的bug 目录 1、Text组件显示泰语2、TextMeshPro组件显示泰语 现在很多游戏都需要显示泰语,下面将介绍Unity如何显示泰语,(仅介绍Unity字体方面的设…

编程网站scratch网址建设项目自主验收验收网站

Vue3中reactive和ref对比 数据角度对比原理角度对比使用角度对比 数据角度对比 ref用来定义: 基本类型reactive用来定义: 对象(或数组)类型数据备注:ref也可以定义对象或数组类型数据,它内部会调用reactive转为代理对象. 原理角度对比 ref通过Object.defineProperty()中的ge…

招聘网站建设技术要求衡阳专业的关键词优化终报价

期刊简介: 【出版社】Elsevier 【影响因子】IF(2022):3.0-4.0 【期刊分区】JCR2区,中科院4区 【检索情况】SCIE 在检,正刊 【参考周期】期刊部系统内提交,预计3个月左右录用,走…

律师推广网站排名网站界面设计案例

UnitTest框架 UnitTest参考文章:https://blog.csdn.net/qq_54219272/article/details/123265794 目标(看完UnitTest框架该有的收获) 掌握UnitTest框架的基本使用方法掌握断言(判断实际结果和预期结果是否一致)的使用方…

厦门模板网站建设亦庄网站开发公司

文章主要讲述px4 如何利用vins_fusion里程计数据实现在室内定位功能。 文章基于以下软、硬件展开。 硬件软件机载电脑: Intel NUC系统:Ubuntu 20.04相机: Intel Realsense D435iros:noetic飞控:Pixhawk 2.4.8固件&am…

网站关键词怎么优化排名wordpress 引用 格式

原文地址:http://www.oschina.net/p/spring-oauth-server?fromerrvpTctDBF转载于:https://www.cnblogs.com/longshiyVip/p/5052657.html

昆明网站开发wordpress 搜索框 位置

之前写过的相关文章: MQTT协议(转载)——筑梦之路_mqtt url-CSDN博客 k8s 部署mqtt —— 筑梦之路-CSDN博客 CentOS 7 搭建mqtt服务——筑梦之路_腾讯云宝塔搭 centos 7.9.2009 x86_64 建标准mqtt服务器-CSDN博客 mqtt简介 MQTT&#xff…

企业网站四种类型一个人开发游戏难吗

当Windows与Linux作为VPS云主机操作系统的对比时,需要专注于小企业主最相关的因素,一个明显的赢家出现了,现在我们来看看吧。Linux与Windows的比较:任何虚拟主机操作系统都应该快速且稳定,但当企业选择VPS主机时&#…

沈阳市网站建设报价网站流量利用

git tag 以及git 一、先说收获吧 1. git bash 在windows上 类似于linux的bash提供的shell命令行窗口,可以执行很多linux命令,cd pwd ls vim cat touch mkdir,还可以用正则匹配查看标签。相当于在windows上装了一个小的linux。git init myproj…

企业网站开发douyanet一起装修网口碑怎么样

最近和一个1000人规模公司的智能制造部门进行交流,参会人员包括部门领导、技术人员、产品(经理)设计人员等,我介绍了工业信息建设相关理念、钢铁云及其他建设案例、iNeuOS工业互联网系统相关内容,交流期间他们领导说了…

玉溪网络推广 网站建设衣服定制的app有哪些

Docker基础教程 Docker简介 Docker基本操作 Docker应用 Docker自定义镜像 Docker compose 为什么使用DockerDocker简介安装DockerDocker的中央仓库Docker镜像操作Docker容器操作准备一个web项目创建MySQL容器创建Tomcat容器将项目部署到TomcatDocker数据卷DockerfileDock…

网站js代码检测seo网站优化案例

目录 1.进入电脑BIOS,设置电脑第一启动项为U盘启动2.进入微pe系统3.然后点击界面最左下方的Windows图标4.点击windows密码选择对应用户名称修改; 1.进入电脑BIOS,设置电脑第一启动项为U盘启动 把u盘插到要清除密码的电脑,然后开机…

基础网站建设公司兼职网站编辑怎么做

摘 要 信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古…