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,一经查实,立即删除!

相关文章

mybatis分页实现总结

1.mybatis拦截器相关知识 1.作用 mybatis的拦截器是mybatis提供的一个拓展机制&#xff0c;允许用户在使用时根据各自的需求对sql执行的各个阶段进行干预。比较常见的如对执行的sql进行监控&#xff0c;排查sql的执行时间&#xff0c;对sql进行拦截拼接需要的场景&#xff0c…

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…

哈希表函数 —— uthash的简单使用

目录标题 哈希表函数 —— uthash的简单使用添加头文件定义结构体哈希表的初始化哈希表的添加哈希表的添加哈希表的排序 哈希表函数 —— uthash的简单使用 添加头文件 在使用uthash函数实现哈希表前&#xff0c;要先添加头文件&#xff1a; #include "uthash.h"定…

Dubbo面试回答简单版

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

链表算法题总结(二十一天)

203. 移除链表元素 题目 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5]示例 2&#xff1a; 输入&…

正方形(c++题解)

题目描述 给定一组不同长度的木棍&#xff0c;是否有可能将它们端对端地连接起来形成 个正方形? 输入格式 第1行输入包含N&#xff0c;即测试数据的数量。 每组测试数据第一个数为 &#xff0c;即木棒的根数。之后有 个整数&#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;…

【每日刷题】Day13

1. 1041. 困于环中的机器人 - 力扣&#xff08;LeetCode&#xff09; //思路&#xff1a;可以利用轴上四个方向的单位坐标表示机器人的运动。遍历字符串&#xff0c;根据字符串内容进行相应的行动。 bool isRobotBounded(char* instructions) { int arr[4][2] {{0,1},{1,0},{0…

Redis漏洞利用

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

CF Educational Codeforces Round 164 Div.2 D. Colored Balls 题解

Colored Balls 题目描述 There are balls of n n n different colors; the number of balls of the i i i-th color is a i a_i ai​. The balls can be combined into groups. Each group should contain at most 2 2 2 balls, and no more than 1 1 1 ball of each c…

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

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

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

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

文件上传下载

文章目录 文件上传下载文件上传文件下载 文件上传下载 HTTP请求会包含一个请求头&#xff0c;其中"Content-Type"字段告诉服务器正在发送什么类型的数据。根据发送的数据类型&#xff0c;浏览器和服务器会采取适应的处理方式。 "multipart/form-data"是一…

基于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;创建一…

富格林:专研正规技巧助力出金

富格林指出&#xff0c;现货黄金拥有诸多其他投资产品无法比拟的交易优势&#xff0c;如此一来吸引着越来越多投资者相继涌入现货黄金市场。但有不少投资者发现自己的出金效率与他人的有差异。为什么会这样呢&#xff1f;其实在现货黄金市场中需要有正规技巧的支持才可以更好地…