C++进阶之AVL树

个人主页:点我进入主页

专栏分类:C语言初阶  C语言进阶  数据结构初阶    Linux    C++初阶     C++进阶​    ​​​​算法

欢迎大家点赞,评论,收藏。

一起努力,一起奔赴大厂

目录

一.前言

二.插入

三.旋转 

3.1右旋

3.2左旋

3.3左右双旋

3.4右左双旋

四.测试


一.前言

        在看这篇博客之前需要了解二叉搜索树的相关内容,可以看这篇博客二叉搜索树,AVL树可以看成为了解决二叉搜索树的问题,它保证了左右子树高度差不超过1。本次的内容的重点就是对AVL树的旋转。

二.插入

        AVL树的插入规则和二叉搜索树的插入规则类似,左子树都小于父节点,右子树都大于父节点,在这里我们引入了一个平衡因子,我们先插入后然后进行调节平衡因子,平衡因子的计算=右子树的高度-左子树的高度,插入的新节点的平衡因子为0,当插入的节点在父节点的右边,父节点的平衡因子+1,当插入的节点在父节点的左边,父节点的平衡因子-1,当整后父节点的平衡因子为0时直接结束,不需要继续调整,当调整后父节点的平衡因子为+1或者-1时需要继续向上进行调整,当调整后父节点的平衡因子为+2或-2时需要进行旋转。我们看下面的代码实现:

bool insert(const pair<K, V>& kv)
{Node* newnode = new Node(kv);if (_root == nullptr) _root = newnode;else{Node* cur = _root, * parent = nullptr;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;}else  return false;}if (kv.first < parent->_kv.first) parent->_left = newnode;else parent->_right = newnode;newnode->_parent = parent;//调整平衡因子while (parent){if (newnode == parent->_left) parent->_bf--;else parent->_bf++;if (parent->_bf == 0) break;else if (parent->_bf == 1 || parent->_bf == -1){newnode = parent;parent = parent->_parent;}else if (parent->_bf == 2 || parent->_bf == -2){if (parent->_bf == 2 && newnode->_bf == 1){RatoteL(parent);}else if (parent->_bf == -2 && newnode->_bf == -1){RatoteR(parent);}else if (parent->_bf == 2 && newnode->_bf == -1){RatoteRL(parent);}else if (parent->_bf == -2 && newnode->_bf == 1){RatoteLR(parent);}else{assert(false);}break;}else{assert(false);}}}return true;
}

三.旋转 

        旋转有4种方式:向右旋转,向左旋转,左右双旋,右左双旋这四种

3.1右旋

        看下面的抽象图

 当n=0时全图为

当n=1时全图为

当n=2时我们有3种,但是在a的位置能放第3种,因为别的会自动进行旋转,b和c这三种都可以

  当n=3时就会更多,所以这是列举不完的,针对右旋我们以下面这张图为例:

我们经过右旋后转化成下面的样子,针对的主要就是这几个节点

 

在旋转的过程中需要注意的是,parent节点是不是根节点,注意调整后subL节点的的父节点的调整,还有一点就是subLR是否为空节点,调整后需要将subL节点和parent节点的bf值改为0,我们看下面的代码:

	void RatoteR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;subL->_right = parent;parent->_left = subLR;Node* ppNode = parent->_parent;subL->_parent = parent->_parent;parent->_parent = subL;if (subLR)subLR->_parent = parent;if (parent == _root){_root = subL;}else{if (ppNode->_left == parent)ppNode->_left = subL;elseppNode->_right = subL;}subL->_bf = parent->_bf = 0;}

3.2左旋

        左旋的代码和右旋的类似,不过需要调节的平衡因子为2和1,我们看下面的图片

我们直接上代码:

void RatoteL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;Node* ppNode = parent->_parent;parent->_parent = subR;subR->_left = parent;subR->_parent = ppNode;if (parent == _root){_root = subR;}else{if (ppNode->_left == parent)ppNode->_left = subR;elseppNode->_right = subR;}subR->_bf = parent->_bf = 0;
}
void RatoteRL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RatoteR(subR);RatoteL(parent);if (bf == 1){parent->_bf = -1;}else if (bf == -1){subR->_bf = 1;}}

3.3左右双旋

        左右双旋的图片可以看为下面的抽象图:

当我们在b位置插入后再旋转,可以得到:

当我们插入到c位置后再经过旋转,可以得到:

 

当只旋转一次就会做一次镜像旋转,我们先让subL节点左旋,然后让parent右旋,然后进行调节平衡因子,我们看代码:

void RatoteLR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RatoteL(subL);RatoteR(parent);if (bf == 1){subL->_bf = -1;}else if (bf == -1){parent->_bf = 1;}
}

3.4右左双旋

        这个和左右双旋类似,我们直接看代码:

	void RatoteRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RatoteR(subR);RatoteL(parent);if (bf == 1){parent->_bf = -1;}else if (bf == -1){subR->_bf = 1;}}

四.测试

        我们直接上代码:

public:	void InOrder(){_InOrder(_root);}bool IsBalance(){return _IsBalance(_root);}
private:void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_kv.first << "->" << root->_kv.second << endl;int left = _height(root->_left);int right = _height(root->_right);int sub = abs(left - right);cout << "bf-> " << sub<<endl;if (sub >= 2) cout<<"key-> "<< root->_kv.first << endl;_InOrder(root->_right);}int _height(Node* root){if (root == nullptr)return 0;int x = 1 + _height(root->_left);int y = 1 + _height(root->_right);return max(x , y);}bool _IsBalance(Node* root){		if (root == nullptr) return true;int left = _height(root->_left);int right = _height(root->_right);if (abs(right - left) >= 2){return false;}return _IsBalance(root->_left) && _IsBalance(root->_right);}

测试代码:

int main()
{srand(0);AVLTree<int, int> a;vector<int> v;for (int i = 0; i < 1000000; i++){int num = rand() + i;v.push_back(num);}cout << a.IsBalance() << endl;return 0;
}

运行可以看到:

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

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

相关文章

如何利用数据仓库进行业务分析:一名大数据工程师的视角

在大数据时代&#xff0c;数据的有效利用对企业的成功至关重要。 本文将基于上面的流程图&#xff0c;详细介绍如何利用数据仓库进行业务分析&#xff0c;并提供实际的例子和代码演示&#xff0c;以帮助读者更好地理解和应用相关技术。 数据仓库的基本流程 上图展示了一个典…

莱辅络Rebro BIM机电专业软件

莱辅洛&#xff08;Rebro&#xff09;是一款专业机电 BIM 软件。它具备专业人士所期待的各种专业功能&#xff0c;应用于建筑机电工程的三维设计&#xff0c;并且适用于建筑、结构、给排水、暖通、电气五大专业。 该软件具有以下特点&#xff1a; • 3D 模型&#xff1a;可以…

1.接口测试-postman学习

目录 1.接口相关概念2.接口测试流程3.postman基本使用-创建请求&#xff08;1&#xff09;环境&#xff08;2&#xff09;新建项目集合Collections&#xff08;3&#xff09;新建collection&#xff08;4&#xff09;新建模块&#xff08;5&#xff09;构建请求请求URLheader设…

常见的创建型设计模式( 一 )

设计模式( 一 ) 常见的创建型设计模式 1.单例模式 : 确保一个类只有一个实例 , 为整个程序提供一个全局的访问接口。getInstance 实现方式 饿汉式&#xff0c;在调用getInstance 创建实例的时候 &#xff0c;实例已经存在了 &#xff0c;不需要我们再次去 new创建。 优点&a…

修复 Android 手机卡在启动屏幕上的 7 种方法

Android 手机卡在启动屏幕上的情况并不常见。通常&#xff0c;问题出现在应用新更新或安装未知来源的应用程序后。幸运的是&#xff0c;您可以让您的 Android 手机跳过启动屏幕&#xff0c;而无需前往最近的服务中心。 当您的 Android 手机在启动屏幕上陷入无限循环时&#xf…

标准立项 | 《温室气体排放核算与报告要求 废油资源化企业》

《温室气体排放核算与报告要求 废油资源化企业》适用于废油资源化行业企业温室气体排放量的核算和报告。从事废油资源化生产的企业&#xff0c;均可参考该标准核算企业的温室气体排放量&#xff0c;并编制企业温室气体排放报告。 参编咨询&#xff1a;中华环保联合会水环境治理…

ECharts 蓝色系-荧光图标折线图01案例

ECharts 蓝色系-荧光图标折线图01案例 图表意义 本折线图案例展示了一周内不同路线的使用情况或数据统计。通过折线的上升和下降&#xff0c;可以直观地观察到每条路线的流量或数据变化趋势&#xff0c;从而进行分析和决策。 效果预览 效果图展示不同路线的数据统计和个性化…

<Rust><iced>在iced中显示gif动态图片的一种方法

前言 本文是在rust的GUI库iced中在窗口显示动态图片GIF格式图片的一种方法。 环境配置 系统&#xff1a;window 平台&#xff1a;visual studio code 语言&#xff1a;rust 库&#xff1a;iced、image 概述 在iced中&#xff0c;提供了image部件&#xff0c;从理论上说&…

链表中环的入口节点

链表中环的入口节点 描述 链表中环的入口节点 给一个长度为n链表&#xff0c;若其中包含环&#xff0c;请找出该链表的环的入口结点&#xff0c;否则&#xff0c;返回null。 数据范围&#xff1a; n≤10000&#xff0c; 1<结点值<10000 要求&#xff1a;空间复杂度 O(1)…

前后端交互的弯弯绕绕

前后端交互&#xff1a; &#x1f197;&#xff0c;收拾一下心情让我们来聊一聊AJax吧&#xff0c;随着前端的飞速发展&#xff0c;前后的交互也发生了天翻地覆的变化&#xff1a; 前后端交互的方式有很多&#xff1a; AJAX、表单提交、WebSocket、RESTful API、... 这对新入…

基于Java学生选课管理系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;…

NSSCTF-Web题目14

目录 [CISCN 2019华东南]Web11和[NISACTF 2022]midlevel 1、题目 2、知识点 3、思路 [HDCTF 2023]SearchMaster 1、题目 2、知识点 3、思路 [CISCN 2019华东南]Web11和[NISACTF 2022]midlevel 这两道题目一样 1、题目 2、知识点 SSTI&#xff08;服务端模板注入漏洞&…

有哪些骨传导耳机是比较推荐入手的?精选五款热门骨传导耳机推荐!

耳机基本是每人人手一台&#xff0c;不管是在地铁上还是在公交上&#xff0c;都可以看到很多人戴着耳机度过空余的时光&#xff0c;甚至现在人们在耳机的选择方面更加偏向于骨传导耳机&#xff0c;开放耳道的奇特设计在户外佩戴的时候可以更好的感知到周围的环境音&#xff0c;…

Github 2024-06-22 开源项目日报 Top10

根据Github Trendings的统计,今日(2024-06-22统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量TypeScript项目3JavaScript项目2Python项目2HTML项目1Rust项目1Dart项目1Dockerfile项目1Shell项目1C++项目1Swift项目1RustDesk: 用Rust编写的…

小程序 获取插件用户openpid?

接口英文名 getPluginOpenPId 功能描述 通过 wx.pluginLogin 接口获得插件用户标志凭证 code 后传到开发者服务器&#xff0c;开发者服务器调用此接口换取插件用户的唯一标识 openpid。 调用方式 HTTPS 调用 第三方调用 调用方式以及出入参和HTTPS相同&#xff0c;仅是调…

跨境电商-Ozon平台开店指南-魔行观察

商家入驻开店指南 第1步&#xff1a;注册并激活您的帐户 对于独联体以外的卖家&#xff1a;法人实体可以在平台上注册。如果您是个体经营户&#xff0c;请您首先开设一家公司。个体经营户&#xff08;土耳其的个体经营户除外&#xff09;不能在我们的平台上注册。 进行注册 …

MarkDown基础

一、MarkDown标题 1.使用和-表示一级标题 2.使用#、##、###、####、######、######表示一级至六级标题 一级标题 二级标题 一级标题 二级标题 三级标题 四级标题 五级标题 六级标题 二、MarkDown标题 1.Markdown 段落没有特殊的格式&#xff0c;直接编写文字就好&#xff0c;…

攻防世界-pdf

方法一&#xff1a;打开是pdf格式的文件&#xff0c;里面有一张图&#xff0c;题目提示图下面什么都没有&#xff1f;emmm用chrom打开pdf——ctrlf搜索flag&#xff0c;里面是有东西的&#xff0c;ctrla复制就可以了。 方法二&#xff1a;题目提示图下面什么都没有&#xff0c;…

FaceFusionSharp OnnxRuntime版 视频换脸

FaceFusionSharp OnnxRuntime版 视频换脸 目录 效果 项目 代码 下载 其他 效果 FaceFusionSharp OnnxRuntime版效果 项目 代码 using OpenCvSharp; using System; using System.Collections.Generic; using System.Drawing; using System.Threading; using System.Window…

炸裂!Claude 3.5 正式发布!超越 GPT-4o!

Anthropic 又憋了个大招&#xff01;推出了 Claude 3.5 Sonnet&#xff01;速度是 Claude 3 的两倍&#xff01;而且数学和编码能力已经超过了 GPT-4o&#xff01; 官方声称&#xff1a;这是我们迄今为止最智能的模型。 直接看测评图&#xff0c;很多指标都吊打 GPT-4o&#xf…