C++实现AVL树

文章目录

    • 一、平衡树的优势
    • 二、二叉平衡搜索树的节点定义
    • 三、二叉搜索树的插入
      • 3.1 寻找插入位置
      • 3.2 开始判定平衡因子,平衡因子有变就开始旋转
        • 3.2.1 左旋的情况
        • 3.2.2 左旋代码(一定要考虑平衡因子为2或者-2的节点是否有父节点)
        • 3.2.2 右旋的情况
        • 3.2.3 左右双旋的情况(细分为3种情况)
          • 3.2.3.1 以下为例3的左子树为h时
          • 3.2.3.2 以下为例3的右子树为h时
          • 3.2.3.3 如果3的右子树为空时
          • 3.2.3.4 代码演示
        • 3.2.4 右左双旋的情况(一样细分三种情况)
    • 四、平衡树的检验(是否平衡)
      • 4.1 先从高度方面检验
      • 4.2 再看树的节点个树
      • 4.3 最后看树的平衡因子
    • 五、全部源码

在这里插入图片描述


先赞后看,养成习惯!!!^ _ ^<3 ❤️ ❤️ ❤️
码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘了关注我哦!
所属专栏:C++进阶

在这里插入图片描述

一、平衡树的优势

经过了解二叉搜索树的性质之后,我们也发现了它极大的缺陷,如果数字基本上都是趋于有序的情况下,那么查找效率非常低下,时间复杂度为O(n),与顺序表的查找一样,因此我们引出了二叉平衡搜索树(AVL树),该树的优势在于能够保证根节点左右子树的高度差的绝对值小于等于1,这就很好保证了查找效率O(logn),如下图就是二叉平衡搜索树的样子。
在这里插入图片描述

二、二叉平衡搜索树的节点定义

由于二叉平衡搜索树需要对节点进行旋转,我们这里引入了父节点的指针,还有平衡因子(保证节点处于平衡状态)
在这里插入图片描述

三、二叉搜索树的插入

3.1 寻找插入位置

首先插入顺序还是和二叉搜索树大差不差,有区别的位置是需要判断平衡因子是否大于1,大于1就要开始旋转了(这里就略过,需要看具体操作可以看二叉搜索树那一章)
在这里插入图片描述

3.2 开始判定平衡因子,平衡因子有变就开始旋转

3.2.1 左旋的情况

在这里插入图片描述

在这里插入图片描述

3.2.2 左旋代码(一定要考虑平衡因子为2或者-2的节点是否有父节点)

在这里插入图片描述

3.2.2 右旋的情况

在这里插入图片描述
在这里插入图片描述

3.2.3 左右双旋的情况(细分为3种情况)
3.2.3.1 以下为例3的左子树为h时

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
一定要注意平衡因子的变化

3.2.3.2 以下为例3的右子树为h时

在这里插入图片描述
在这里插入图片描述

3.2.3.3 如果3的右子树为空时

那么平衡因子都为0,其他变化都是一样的

3.2.3.4 代码演示

在这里插入图片描述

3.2.4 右左双旋的情况(一样细分三种情况)

下面只讲解一种情况其他都是一样的就是平衡因子发生改变

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、平衡树的检验(是否平衡)

4.1 先从高度方面检验

在这里插入图片描述

4.2 再看树的节点个树

在这里插入图片描述

4.3 最后看树的平衡因子

在这里插入图片描述

五、全部源码

#pragma once
#include<iostream>
#include<vector>
#include<assert.h>
//#include <utility> 
using namespace std;
template<class K,class V>
struct AVLTreeNode
{AVLTreeNode<K,V>* _left;AVLTreeNode<K, V>* _right;AVLTreeNode<K, V>* _parent;int _bf;pair<K, V> _kv;//构造函数初始化列表AVLTreeNode(const pair<K, V> kv):_left(nullptr), _right(nullptr), _parent(nullptr), _bf(0), _kv(kv){}
};template<class K, class V>
class AVLTree
{typedef AVLTreeNode<K, V> Node;
public: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->_left = cur;elseparent->_right = cur;cur->_parent = parent;while (parent){if (cur == parent->_left){parent->_bf--;//左为减}else{parent->_bf++;}if (parent->_bf == 1 || parent->_bf == -1){cur = 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{RotateRL(parent);}break;}}return true;}void RotateL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;if (subRL)subRL->_parent = parent;parent->_right = subRL;Node* pp = parent->_parent;subR->_left = parent;if (pp == nullptr){parent->_parent = subR;_root = subR;subR->_parent = nullptr;}else{if (pp->_left == parent){parent->_parent = subR;subR->_parent = pp;pp->_left = subR;}else if (pp->_right == parent){parent->_parent = subR;pp->_right = subR;subR->_parent = pp;}else{assert(false);}}parent->_bf = subR->_bf = 0;}void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;if (subLR)subLR->_parent = parent;parent->_left = subLR;Node* pp = parent->_parent;subL->_right = parent;if (pp == nullptr){_root = subL;subL->_parent = nullptr;}else{if (pp->_left == parent){parent->_parent = subL;subL->_parent = pp->_left;}else if (pp->_right = parent){parent->_parent = subL;subL->_parent = pp->_right;}else{assert(false);}}parent->_bf = subL->_bf = 0;}void RotateLR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RotateL(subL);RotateR(parent);if (bf == -1){parent->_bf = -1;subLR->_bf = 0;subL->_bf = 0;}else if (bf == 1){parent->_bf = 0;subLR->_bf = 0;subL->_bf = 1;}else if (bf == 0){parent->_bf = subLR->_bf = subL->_bf = 0;}else{assert(false);}}void RotateRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(subR);RotateL(parent);if (bf == -1){parent->_bf = 0;subRL->_bf = 0;subR->_bf = 1;}else if (bf == 1){parent->_bf = -1;subRL->_bf = 0;subR->_bf = 0;}else if (bf == 0){parent->_bf = subRL->_bf = subR->_bf = 0;}else{assert(false);}}void _Inorder(){Inorder(_root);}void Inorder(Node* root){if (root == nullptr)return;Inorder(root->_left);cout << root->_kv.first << endl;Inorder(root->_right);}Node* Find(const pair<K,V> kv){Node* cur = _root;while (cur){if (cur->_kv.first > kv.first){cur = cur->_left;}else if (cur->_kv.first < kv.first){cur = cur->_right;}else{return cur;}}return nullptr;}size_t _Height()//树的高度{return Height(_root);}size_t Height(Node* root){if (root == nullptr)return 0;int leftHeight = Height(root->_left);int rightHeight = Height(root->_right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;}//数的节点个树size_t _Size(){return Size(_root);}size_t Size(Node* root){if (root == nullptr)return 0;return Size(root->left) + Size(root->right) + 1;}//判断树是否平衡bool _Isbalance(){return Isbalance(_root);}bool Isbalance(Node* root){if (root == nullptr)return false;int leftHeight = Height(root->_left);int rightHeight = Height(root->_right);return abs(leftHeight - rightHeight) < 2&& Isbalance(root->_left) && Isbalance(root->_right);//检查完当前树的高度//然后就检查当前树的左子树和右子树是否符合要求}private:Node* _root = nullptr;};

在这里插入图片描述

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

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

相关文章

DC-5渗透测试复现

DC-5渗透测试复现 目的&#xff1a; 获取最高权限以及5个flag 过程&#xff1a; 信息打点-文件包含漏洞-弹shell- scren-4.0.5提权 环境&#xff1a; 攻击机&#xff1a;kali(192.168.85.136) 靶机&#xff1a;DC_3(192.168.85.134) 复现&#xff1a; 一.信息收集 nma…

PlantUML 实战示例(使用 PlantUML 画用例图、类图、活动图、时序图)

目录 前言 需求场景 用例图 类图 活动图 时序图 前言 在软件开发的生命周期中&#xff0c;需要先进行设计&#xff0c;最后才是进行具体的编码和测试。设计时就需要画各种 UML 图&#xff0c;有专业的 UML 画图软件&#xff0c;也有很多在线的 UML 画图网站可以来画图&a…

Dubbo面试回答简单版

一、dubbo特性 超时重试机制地址缓存多版本负载均衡&#xff1a;随机、权重轮询、最少活跃调用、一致性哈希集群容错&#xff1a;失败重试、快速失败、失败安全、失败自动恢复、并行调用、广播服务降级&#xff1a;异常时返回mock 集群容错 FailOver 失败重试&#xff0c;读…

求存款本息和(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h> # include <math.h>int main() {//初始化变量值&#xff1b;double P 1000, r1 0.015, r2 0.021, r3 0.0275, r4 0.03, r5 0.0035;int judge 0;//…

富文本编辑器的下载安装使用

为什么选择vue-quill-editor&#xff1f; 在众多的富文本编辑器中&#xff0c;vue-quill-editor因其易用性、灵活性以及对Vue框架友好的特性而受到开发者的青睐。它基于Quill编辑器&#xff0c;Quill是一款现代的WYSIWYG&#xff08;所见即所得&#xff09;编辑器&#xff0c;…

Redis漏洞利用

未授权 可以利用超级弱口令工具来判断redis是否能未授权登录 telnet #尝试登录info #查看redis信息 RCE方法 写shell 需要写权限需要知道web网站路径 config set dir /var/www/html config set dbfilename redis.php set test "<?php phpinfo(); ?>" sa…

UI设计/交互设计/视觉设计项目汇报/作品集Figma/PPT模板

作为UI设计/交互设计/视觉设计师&#xff0c;创建作品集对于向潜在客户或雇主展示您的技能、创造力和风格至关重要。以下分步指南可帮助您创建令人印象深刻的作品集&#xff1a; 选择您的最佳作品&#xff1a;选择您最强大且最相关的设计项目&#xff0c;将其纳入您的作品集。…

AI人工智能讲师大模型培训讲师叶梓 大语言模型(LLM)在科学文献摘要领域的应用

大语言模型&#xff08;LLM&#xff09;在科学文献摘要领域的应用是一个前沿且迅速发展的技术趋势。通过结合GitHub上yobibyte的Compressor项目&#xff0c;我们可以深入探讨这一技术方案的潜力和实现方式。 技术背景 随着科学研究的快速发展&#xff0c;每天都有大量的科学文…

基于8B/10BGT收发器的PHY层设计(1)

一、PHY层简介 PHY层&#xff08;Physical Layer&#xff09;是OSI模型中最低的一层&#xff0c;也是最基本的一层&#xff0c;PHY是物理接口收发器&#xff0c;它实现物理层。包括MII/GMII&#xff08;介质独立接口&#xff09;子层、PCS&#xff08;物理编码子层&#xff09…

王道汽车4S企业管理系统 SQL注入漏洞复现

0x01 产品简介 王道汽车4S企业管理系统(以下简称“王道4S系统”)是一套专门为汽车销售和维修服务企业开发的管理软件。该系统是博士德软件公司集10余年汽车行业管理软件研发经验之大成,精心打造的最新一代汽车4S企业管理解决方案。 0x02 漏洞概述 王道汽车4S企业管理系统…

SQL语言自用(持续更新)+实验记录

课本:《数据库原理及其应用教程》&#xff08;第四版&#xff09; (主编)黄德才&(副主编)陆亿红 实验&#xff1a;学校实验课材料 其他&#xff1a; [ ]表示可以被删除&#xff0c;也表示可以被替换&#xff0c;请自行判断。如果有一些截图或照片&#xff0c;是暂时懒得整…

5、LMDeploy 量化部署 LLMVLM实战(homework)

基础作业&#xff08;结营必做&#xff09; 完成以下任务&#xff0c;并将实现过程记录截图&#xff1a; 配置lmdeploy运行环境 由于环境依赖项存在torch&#xff0c;下载过程可能比较缓慢。InternStudio上提供了快速创建conda环境的方法。打开命令行终端&#xff0c;创建一…

鸿蒙开发快速入门

基本概念 ArkTS 因为ArkTS是基于Type Script扩展而来&#xff0c;是Type Script的超集&#xff0c;所以也可以关注一下Type Script的语法来理解ArkTS的语法 ArkUI HarmonyOS提供了一套UI开发框架&#xff0c;即方舟开发框架&#xff08;ArkUI框架&#xff09;。方舟开发框架…

【日常记录】【CSS】SASS循环的使用

文章目录 1、引言2、安装3、举例4、参考链接 1、引言 目前在任何项目框架中&#xff0c;都会有css 预处理器&#xff0c;目前一般使用 sass、less 这俩其中之一&#xff0c;它可以简化css的书写 Sass 是一款强化 CSS 的辅助工具&#xff0c;它在 CSS 语法的基础上增加了变量 (v…

【深度学习实战(2)】如何使用matplotlib.pyplot模块记录自己的训练,验证损失

一、matplotlib库 在我们自己训练模型时&#xff0c;常常会使用matplotlib库来绘制oss和accuracy的曲线图&#xff0c;帮助我们分析模型的训练表现。 matplotlib库安装&#xff1a;pip install matplotlib 二、代码 import matplotlib.pyplot as plt import torch import to…

设计模式-组合模式(Composite Pattern)

1. 概念 组合模式是一种结构型设计模式&#xff0c;它允许将对象组合成树状的层次结构&#xff0c;用来表示“整体-部分”的关系。 2. 原理结构图 原理图 抽象角色&#xff08;Component&#xff09;&#xff1a;这是组合模式的核心&#xff0c;它定义了树叶和树枝构件的公…

【产品经理修炼之道】- 融资租赁相关业务介绍

一、什么是融资租赁&#xff1f; 根据《民法典》第735条的规定&#xff0c;融资租赁合同是出租人根据承租人对出卖人、租赁物的选择&#xff0c;向出卖人购买租赁物&#xff0c;提供给承租人使用&#xff0c;承租人支付租金的合同。 例如&#xff0c;A工厂因业务发展需要欲购置…

c/c++普通for循环学习

学习一下 for 循环的几种不同方式&#xff0c;了解一下原理及差异 完整的测试代码参考 GitHub &#xff1a;for 循环测试代码 1 常用形态 对于 for 循环来说&#xff0c;最常用的形态如下 for (表达式1; 表达式2; 表达式3) {// code }流程图如下&#xff1a; 编写测试代码…

stack和queue模拟实现

前言 上一期我们介绍了stack和queue的使用&#xff0c;本期我们来模拟实现一下他们&#xff01; 本期内容介绍 容器适配器 deque介绍 为什么stack和queue的底层选择deque为默认容器&#xff1f; stack 模拟现实 queue 模拟实现 什么是容器适配器&#xff1f; 适配器是一种设…

springboot抑郁症科普知识测试系统ssm-java

本系统设计了二种角色&#xff1a;管理员&#xff0c;用户。通过此系统&#xff0c;管理员可以在线视频、案例展示、、测试试卷、测试试题进行测试。以及在线对测试试卷进行批阅和批量删除&#xff0c;用户可以对自己的测试试卷进行测试&#xff0c;对管理员已经批阅过的试卷可…