算法与数据结构--二叉搜索树与自平衡二叉搜索树

0.字典(即c++的map)

注:字典的 "member运算" 指的是检查字典中是否存在某个特定的键的操作,即查询操作。

如果我们使用数组来实现字典/map,虽然使用二分法查询也可以达到logn,但是的话插入和删除太慢了。使用链表实现的话虽然插入和删除是O(1),但是查询的话达到了O(n),也不可取。

因此人们发明了自平衡二叉查找树,在保证查找效率的同时,又保证了插入和删除的效率,从而更好的实现字典。

c++的map和set就是用红黑树来实现的(一种特殊的自平衡二叉搜索树)。而unorder_map使用哈希表实现的。

1.二叉查找树--BST

在讲自平衡二叉搜索树之前,我们要先明白什么是二叉搜索树。

二叉查找树(Binary Search Tree),是具有如下性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

二叉搜索树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势;所以应用十分广泛,例如在文件系统和数据库系统一般会采用这种数据结构进行高效率的排序与检索操作。

使用二叉搜索树进行添加,删除,搜索的平均时间复杂度都为O(logn)

2.自平衡二叉查找树--AVL树

1.为什么要有AVL树

二叉查找树虽然平均添加,删除,查找效率为O(logn),但是却不稳定,比如像上面这张图,在最坏的情况下,也就是该二叉树不平衡的时候,效率又降到了O(n)。

所以我们要想办法让这颗二叉查找树平衡,让结点平均地分布在树的两侧,从而提高算法的稳定性,于是就发明了自平衡二叉搜索树,即AVL树。

2.AVL树的定义

3.如何构建AVL树

具体流程:

元素插入二叉搜索树中->判断结点是否平衡,具体是那种情况的不平衡->根据所处的不平衡情况进行不同的调整策略

当遇到结点不平衡时:

根据插入元素的落点,调整策略分为四种情况,插入元素落入以下4个子树的情况分别对应着四种状态。

【1】右旋--LL型状态

这时候对A结点,也就是根结点使用右旋操作进行调整。A连接左子树的右子树,A称为B的右子树。

【2】左旋--RR型状态

这时候对根结点使用左旋操作。

【3】先左旋后右旋--LR型状态

采用LR双旋。

这个操作等效与先对B结点作左旋操作,再对A结点作右旋操作。

【4】先右旋后左旋--RL型状态

采用RL双旋。

RL双旋等效于先对C右旋,再对A左旋。

具体代码

// AVL节点的定义
struct AVLNode {int data;AVLNode* left;AVLNode* right;int height;AVLNode(int value) : data(value), left(nullptr), right(nullptr), height(1) {}
};// 获取节点的高度
int getHeight(AVLNode* node) {if (node == nullptr)return 0;return node->height;
}// 计算平衡因子,即左子树的高度减去右子树的高度
int getBalanceFactor(AVLNode* node) {if (node == nullptr)return 0;return getHeight(node->left) - getHeight(node->right);
}// 更新节点的高度
//为左子树高度与右子树高度的最大值加一
void updateHeight(AVLNode* node) {if (node != nullptr) {node->height = 1 + std::max(getHeight(node->left), getHeight(node->right));}
}// 右旋转
AVLNode* rightRotate(AVLNode* y) {AVLNode* x = y->left;AVLNode* T2 = x->right;x->right = y;y->left = T2;updateHeight(y);updateHeight(x);return x;
}// 左旋转
AVLNode* leftRotate(AVLNode* x) {AVLNode* y = x->right;AVLNode* T2 = y->left;y->left = x;x->right = T2;updateHeight(x);updateHeight(y);return y;
}// 插入节点
AVLNode* insertNode(AVLNode* root, int key) {if (root == nullptr) {return new AVLNode(key);}if (key < root->data) {root->left = insertNode(root->left, key);} else if (key > root->data) {root->right = insertNode(root->right, key);} else {// 重复的键值不允许插入return root;}// 更新节点的高度updateHeight(root);// 获取平衡因子int balance = getBalanceFactor(root);// 进行旋转操作以保持平衡// 左子树不平衡if (balance > 1) {if (key < root->left->data) {// 左-左情况,进行右旋转return rightRotate(root);} else {// 左-右情况,先左旋转,再右旋转root->left = leftRotate(root->left);return rightRotate(root);}}// 右子树不平衡if (balance < -1) {if (key > root->right->data) {// 右-右情况,进行左旋转return leftRotate(root);} else {// 右-左情况,先右旋转,再左旋转root->right = rightRotate(root->right);return leftRotate(root);}}// 树保持平衡,直接返回根节点return root;
}

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

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

相关文章

【操作系统】探究进程奥秘:显示进程列表的解密与实战

​&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;Linux专栏&#xff1a;《探秘Linux | 操作系统解密》⏰诗赋清音&#xff1a;月悬苍穹泛清辉&#xff0c;梦随星河徜徉辉。情牵天际云千层&#xff0c;志立乘风意自飞。 ​ 目录 &a…

ImageJ图像滤波基础

文章目录 滤波简单滤波器卷积滤波Unsharp MaskTop Hat ImageJ系列&#xff1a;安装与初步&#x1f48e;灰度图像处理 滤波 预设滤波器 ImageJ的Process菜单提供了诸多图像滤波器&#xff0c;其中大部分方法均可定制参数&#xff0c;但也提供了一些已经预设参数的处理方法。 …

Visual Studio2022配置ReSharper C++ 常用设置

如需安装免费的可以在下面留言&#xff0c;看到即回复 文章目录 Visual Studio2022配置ReSharper C 常用设置配置Visual Studio2022&#xff0c;使其能够按回车进行补全配置ReSharper C 设置自动弹出配置ReSharper C 的快捷键ReSharper C 去掉注释拼写使用中文注释 如何关闭新版…

2007年AMC8数学竞赛中英文真题典型考题、考点分析和答案解析

今天&#xff0c;我们来继续研究AMC8竞赛的真题。通过反复研究历年真题&#xff0c;不仅可以掌握AMC8这个竞赛的命题规律和常见考点&#xff0c;通过真题的详细解析可以建立自己的解题思路、举一反三&#xff0c;还可以通过做真题不断发现自己的薄弱点查漏补缺。 今天我们来看看…

FinGPT:金融大语言模型 | 开源日报 No.127

verdaccio/verdaccio Stars: 15.0k License: MIT Verdaccio 是一个轻量级的 Node.js 私有代理仓库。 以下是 Verdaccio 的核心优势和关键特性&#xff1a; 零配置&#xff1a;无需复杂设置即可快速启动私有 npm 注册表。本地化管理&#xff1a;通过内置小型数据库进行简单而…

Nature | Baker团队用AI设计出史上最高互作强度的蛋白质

蛋白质是生命的基础&#xff0c;是生命功能的主要执行者&#xff0c;其结构与功能由氨基酸序列所决定。蛋白质设计是指对新蛋白质分子进行人为的合理设计&#xff0c;旨在设计新的活性&#xff0c;行为或目的&#xff0c;并增进对蛋白质功能的基本了解。可以从头开始设计蛋白质…

蓝桥杯备赛 day 1 —— 递归 、递归、枚举算法(C/C++,零基础,配图)

目录 &#x1f308;前言 &#x1f4c1; 枚举的概念 &#x1f4c1;递归的概念 例题&#xff1a; 1. 递归实现指数型枚举 2. 递归实现排列型枚举 3. 递归实现组合型枚举 &#x1f4c1; 递推的概念 例题&#xff1a; 斐波那契数列 &#x1f4c1;习题 1. 带分数 2. 反硬币 3. 费解的…

12.25

led.c #include "led.h" void all_led_init() {RCC_GPIO | (0X3<<4);//时钟使能GPIOE_MODER &(~(0X3<<20));//设置PE10输出GPIOE_MODER | (0X1<<20);//设置PE10为推挽输出GPIOE_OTYPER &(~(0x1<<10));//PE10为低速输出GPIOE_OSPEED…

【深度学习目标检测】十一、基于深度学习的电网绝缘子缺陷识别(python,目标检测,yolov8)

YOLOv8是一种物体检测算法&#xff0c;是YOLO系列算法的最新版本。 YOLO&#xff08;You Only Look Once&#xff09;是一种实时物体检测算法&#xff0c;其优势在于快速且准确的检测结果。YOLOv8在之前的版本基础上进行了一系列改进和优化&#xff0c;提高了检测速度和准确性。…

C# 读取Word表格到DataSet

目录 功能需求 Office 数据源的一些映射关系 范例运行环境 配置Office DCOM 关键代码 组件库引入 ​核心代码 杀掉进程 总结 功能需求 在应用项目里&#xff0c;多数情况下我们会遇到导入 Excel 文件数据到数据库的功能需求&#xff0c;但某些情况下&#xff0c;也存…

深圳锐科达SIP矿用电话模块SV-2801VP

深圳锐科达SIP矿用电话模块SV-2801VP 一、简介 SV-2800VP系列模块是我司设计研发的一款用于井下的矿用IP音频传输模块&#xff0c;可用此模块打造一套低延迟、高效率、高灵活和多扩展的IP矿用广播对讲系统&#xff0c;亦可对传统煤矿电话系统加装此模块&#xff0c;进行智能化…

OpenCV之图像匹配与定位

利用图像特征的keypoints和descriptor来实现图像的匹配与定位。图像匹配算法主要有暴力匹配和FLANN匹配&#xff0c;而图像定位是通过图像匹配结果来反向查询它们在目标图片中的具体坐标位置。 以QQ登录界面为例&#xff0c;将整个QQ登录界面保存为QQ.png文件&#xff0c;QQ登…