c/c++|红黑树|分析应用|锚点
红黑树是一种自平衡的二叉查找树,它保持着良好的平衡,能够在插入和删除等操作后通过一系列旋转和重新着色操作来保持树的平衡。这种平衡性质使得红黑树在搜索、插入和删除等操作的平均和最坏情况下的时间复杂度都是O(log n)。以下是红黑树的一些关键特性和性质:每个节点要么是红色,要么是黑色。
根节点必须是黑色。
红色节点的子节点必须是黑色(不存在两个相邻的红色节点)。
从任一节点到其每个叶子的所有路径都包含相同数量的黑色节点,这被称为“黑色平衡”或“黑高度”。
红黑树的基本操作包括插入、删除、查找等。其中,插入和删除操作是通过一系列旋转和重新着色来维护红黑树的平衡性。插入操作:当插入一个新节点时,首先按照二叉查找树的规则找到其应该插入的位置。然后,将新节点插入为红色节点,这样可能会破坏红黑树的某些性质,如颜色相邻节点不能同时为红色。接下来,通过一系列的旋转和重新着色操作来修复这些性质,以确保树的平衡性。删除操作:删除操作也是通过一系列旋转和重新着色来维护树的平衡性。当删除一个节点时,首先按照二叉查找树的规则找到要删除的节点。然后,根据要删除节点的子节点情况进行不同的处理:如果要删除的节点有零个或一个子节点,直接删除即可;如果要删除的节点有两个子节点,则需要找到其后继节点(即比它大的最小节点),并用后继节点替换原节点,然后再删除后继节点。查找操作:查找操作和普通的二叉查找树一样,采用递归或迭代的方式从根节点开始逐级查找,直到找到目标节点或到达叶子节点为止。红黑树的时间复杂度和空间复杂度分析如下:时间复杂度:在红黑树中,搜索、插入和删除操作的平均和最坏情况下的时间复杂度都是O(log n),其中n是树中节点的数量。这是因为红黑树保持了良好的平衡性质,使得树的高度保持在O(log n)级别。因此,即使在最坏情况下,搜索、插入和删除操作的性能也是很高效的。空间复杂度:红黑树的空间复杂度主要取决于节点的数量。每个节点除了存储数据外,还需要存储指向父节点、左子节点和右子节点的指针,以及颜色信息。因此,红黑树的空间复杂度为O(n),其中n是树中节点的数量。
#include <iostream>enum Color { RED, BLACK };template <typename T>
struct Node {T data;Node<T> *left, *right, *parent;Color color;// ConstructorNode(T data) : data(data), left(nullptr), right(nullptr), parent(nullptr), color(RED) {}
};template <typename T>
class RedBlackTree {
private:Node<T> *root;// Private methodsvoid rotateLeft(Node<T> *&);void rotateRight(Node<T> *&);void fixInsertion(Node<T> *&);public:// ConstructorRedBlackTree() : root(nullptr) {}// Public methodsvoid insert(const T&);void printInorder() const;
};// Rotate left
template <typename T>
void RedBlackTree<T>::rotateLeft(Node<T> *&node) {Node<T> *rightChild = node->right;node->right = rightChild->left;if (node->right != nullptr)node->right->parent = node;rightChild->parent = node->parent;if (node->parent == nullptr)root = rightChild;else if (node == node->parent->left)node->parent->left = rightChild;elsenode->parent->right = rightChild;rightChild->left = node;node->parent = rightChild;
}// Rotate right
template <typename T>
void RedBlackTree<T>::rotateRight(Node<T> *&node) {Node<T> *leftChild = node->left;node->left = leftChild->right;if (node->left != nullptr)node->left->parent = node;leftChild->parent = node->parent;if (node->parent == nullptr)root = leftChild;else if (node == node->parent->left)node->parent->left = leftChild;elsenode->parent->right = leftChild;leftChild->right = node;node->parent = leftChild;
}// Fix insertion
template <typename T>
void RedBlackTree<T>::fixInsertion(Node<T> *&node) {Node<T> *parent = nullptr;Node<T> *grandparent = nullptr;while (node != root && node->color != BLACK && node->parent->color == RED) {parent = node->parent;grandparent = parent->parent;// Case : Parent is left child of Grandparentif (parent == grandparent->left) {Node<T> *uncle = grandparent->right;// Case : Uncle is RED, only recoloring requiredif (uncle != nullptr && uncle->color == RED) {grandparent->color = RED;parent->color = BLACK;uncle->color = BLACK;node = grandparent;} else {// Case : Node is right child of Parentif (node == parent->right) {rotateLeft(parent);node = parent;parent = node->parent;}// Case : Node is left child of ParentrotateRight(grandparent);std::swap(parent->color, grandparent->color);node = parent;}} else {// Case : Parent is right child of GrandparentNode<T> *uncle = grandparent->left;// Case : Uncle is RED, only recoloring requiredif (uncle != nullptr && uncle->color == RED) {grandparent->color = RED;parent->color = BLACK;uncle->color = BLACK;node = grandparent;} else {// Case : Node is left child of Parentif (node == parent->left) {rotateRight(parent);node = parent;parent = node->parent;}// Case : Node is right child of ParentrotateLeft(grandparent);std::swap(parent->color, grandparent->color);node = parent;}}}root->color = BLACK;
}// Insert node into the tree
template <typename T>
void RedBlackTree<T>::insert(const T& data) {Node<T> *newNode = new Node<T>(data);Node<T> *parent = nullptr;Node<T> *current = root;while (current != nullptr) {parent = current;if (newNode->data < current->data)current = current->left;elsecurrent = current->right;}newNode->parent = parent;if (parent == nullptr)root = newNode;else if (newNode->data < parent->data)parent->left = newNode;elseparent->right = newNode;fixInsertion(newNode);
}// Inorder traversal
template <typename T>
void inorderHelper(Node<T> *root) {if (root == nullptr) return;inorderHelper(root->left);std::cout << root->data << " ";inorderHelper(root->right);
}// Print tree in inorder
template <typename T>
void RedBlackTree<T>::printInorder() const {inorderHelper(root);
}// Test
int main() {RedBlackTree<int> tree;tree.insert(10);tree.insert(20);tree.insert(30);tree.insert(15);tree.insert(25);std::cout << "Inorder traversal of the tree: ";tree.printInorder();std::cout << std::endl;return 0;
}//输出结果:Inorder traversal of the tree: 10 15 20 25 30
先让gpt回答吧
怎么说呢,说到红黑树,必然先从avl 平衡二叉树讲起
而且红黑树在unordered_map、redis、等数据存储用很多应用
平衡性维护方式:AVL树:通过保持任意节点的左子树和右子树的高度差不超过1来维护平衡。在插入或删除节点时,可能需要进行旋转操作来保持平衡。
红黑树:通过一系列的旋转和重新着色操作来维护平衡。红黑树不追求严格的平衡,但它保证了树的黑高度是O(log n),从而保证了树的高度近似平衡。
旋转次数:AVL树:由于 AVL 树要求严格的平衡,插入或删除操作可能需要进行更多的旋转操作来保持平衡,因此在某些情况下,AVL树的旋转次数会比红黑树多。
红黑树:红黑树的平衡性维护更加宽松,旋转和重新着色的次数相对较少,因此在实践中通常比 AVL 树更高效。
性能特点:AVL树:由于 AVL 树严格追求平衡,因此在查找操作上可能比红黑树更快,因为 AVL 树的高度更低。但是在插入和删除操作上可能更耗时,因为可能需要进行更多的旋转操作。
红黑树:红黑树在插入和删除操作上的性能通常比 AVL 树更好,因为它的平衡性维护更加宽松,旋转和重新着色的次数较少。红黑树在实际应用中更为广泛,例如在C++的STL中就使用了红黑树来实现map和set等容器。
总的来说,AVL树和红黑树都是自平衡的二叉查找树,它们各有优缺点,在不同的应用场景中选择合适的数据结构是很重要的。
关联容器的实现:红黑树常被用作关联容器的底层实现,例如C++ STL中的std::map和std::set就是基于红黑树实现的。这些容器可以快速地进行查找、插入和删除操作,并且保持元素的有序性。数据库索引:数据库系统中经常需要快速地查找和更新数据,红黑树作为一种高效的数据结构,常被用作数据库索引的底层实现。它可以支持快速的数据检索操作,并且保持索引的平衡性。操作系统内核:红黑树在操作系统内核中也有广泛的应用,用于实现各种数据结构和算法。例如,在Linux内核中,红黑树被用于进程调度、文件系统、内存管理等方面。路由表:计算机网络中的路由器常使用红黑树来存储路由表,以支持快速的路由查找和更新。红黑树可以高效地存储和管理大量的网络路由信息,并且保持路由表的平衡性。内存分配器:在动态内存分配器中,红黑树可以用于管理内存分配和释放的元数据,以支持快速的内存分配和释放操作,并且保持内存分配器的高效性和平衡性。总的来说,红黑树作为一种高效的自平衡二叉查找树,具有广泛的应用领域,可以在各种场景中提供高效的数据存储和检索功能。
相关文章:
c/c++|红黑树|分析应用|锚点
红黑树是一种自平衡的二叉查找树,它保持着良好的平衡,能够在插入和删除等操作后通过一系列旋转和重新着色操作来保持树的平衡。这种平衡性质使得红黑树在搜索、插入和删除等操作的平均和最坏情况下的时间复杂度都是O(log n)。以下是红黑树的一些关键特性…...
2-29算法习题总结
贪心问题 小A的糖果 题目描述 小 A 有 n n n 个糖果盒,第 i i i 个盒中有 a i a_i ai 颗糖果。 小 A 每次可以从其中一盒糖果中吃掉一颗,他想知道,要让任意两个相邻的盒子中糖的个数之和都不大于 x x x,至少得吃掉几颗糖…...
当Linux 磁盘满了,查看大文件并删除
当你的Linux磁盘空间满了时,可以通过以下步骤查找大文件并删除它们: 检查磁盘空间: 使用以下命令检查磁盘空间的使用情况: df -h这将显示文件系统的使用情况,包括每个文件系统的总大小、已用空间、可用空间和挂载点。 …...
STL -萃取特性迭代器
1. STL简单概述 a. STL六大组成部分 容器(Container)空间配置器(allocator)算法(Algorithm)迭代器(Iterator)仿函数(Function object)适配器(Ad…...
python pandas写入csv
在Python的Pandas库中,可以使用to_csv方法将DataFrame对象写入CSV文件。以下是一个简单的示例: import pandas as pd# 创建一个DataFrame对象 data {Name: [Alice, Bob, Charlie, David],Age: [25, 30, 35, 40],City: [New York, Los Angeles, Chicago…...
oracle 数据库建集群式数据库的DBLINK的语法
根据需要修改以下红色字体的部分即可。 1、连接集群式数据库DBLINK语法 create public database link 自定义的dblink名字 connect to 连接对方数据库的用户名 identified by "密码" using (DESCRIPTION (ADDRESS_LIST (FAILOVER ON) (LOAD_BALANCE OFF) …...
基于JAVA的毕业设计分配选题系统 开源项目
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 专业档案模块2.2 学生选题模块2.3 教师放题模块2.4 选题审核模块 三、系统展示四、核心代码4.1 查询专业4.2 新增专业4.3 选择课题4.4 取消选择课题4.5 审核课题 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpri…...
Android 接入指纹识别
接入指纹框架:https://github.com/Tencent/soter implementation com.github.Tencent.soter:soter-wrapper:2.0.91.Application中初始化 class IApplication : Application() {override fun onCreate() {super.onCreate()instance thisinitSort()}private fun in…...
如何通过代理IP安全使用Linkedln领英?
LinkedIn是跨境外贸必备的拓客工具,世界各地的许多专业人士都使用领英来作为发布和共享内容的主要工具,这使得它成为跨境出海必备的渠道工具。 但是不少做外贸的朋友都知道,领英账号很容易遭遇限制封禁,但如果善用工具࿰…...
嵌入式驱动学习第一周——定时器与延时函数
前言 这篇博客一起学习定时器,定时器是最常用到的功能之一,其最大的作用之一就是提供了延时函数。 嵌入式驱动学习专栏将详细记录博主学习驱动的详细过程,未来预计四个月将高强度更新本专栏,喜欢的可以关注本博主并订阅本专栏&…...
Tips杂记
🥲 🥸 🤌 🫀 🫁 🥷 🐻❄️🦤 🪶 🦭 🪲 🪳 🪰 🪱 🪴 🫐 🫒 🫑…...
可以用numpy为for加速
Numpy除了用于科学计算,还有一个功能是可以代替某些for循环,进行同样的功能实现,有于是向量矩阵运算,碰到复杂的for时,计算速度可以提高,从而提高程序性能。以下是一些常用的NumPy函数和操作,可…...
cartographer ceres后端优化
这里引用一篇文章 https://zhuanlan.zhihu.com/p/567635409 因为cartographer中的代码有的地方添加了AddParameterBlock,有的地方没有添加,会引起歧义,原来AddParameterBlock可以隐式添加优化变量,这篇文章介绍了具体原因,核心内容如下: AddParameterBlock的作用作用一:…...
day57 集合 List Set Map
List实现类 List接口特点:元素有序 可重复 Arraylist 可变数组 jdk 8 以前Arraylist容量初始值10 jdk8 之后初始值为0,添加数据时,容量为10; ArrayList与Vector的区别? LinkList:双向链表 优点࿱…...
蓝桥杯:真题讲解3(C++版)附带解析
报纸页数 来自:2016年七届省赛大学C组真题(共8道题) 分析: --画出报纸长的样子,如果我们在上面多画一张报纸,那么就符合题意的5,6,11,12。 观察这张图:观察3…...
继续预训练对大语言模型的影响
翻译自文章:Investigating Continual Pretraining in Large Language Models: Insights and Implications 摘要 本文研究了大型语言模型(LLMs)中不断学习(CL)的不断发展领域,重点是制定有效和可持续的训练…...
关于空频变换的知识点
1.DCT变换: 离散余弦变换是一种将图像从空域转换到频域的技术,它可以将图像分解为频域分量。对于RGB图像,它由红色(R)、绿色(G)和蓝色(B)三个通道组成。当应用DCT变换时…...
纯css实现-让字符串在文字少时显示为居中对齐,而在文字多时显示为左对齐
纯css实现-让字符串在文字少时显示为居中对齐,而在文字多时显示为左对齐 使用flex实现 思路 容器样式(.container): Flex容器的BFC性质使得其内部的子元素(.text-box)在水平方向上能够居中,通过justify-c…...
初学HTMLCSS——盒子模型
盒子模型 盒子:页面中所有的元素(标签),都可以看做是一个 盒子,由盒子将页面中的元素包含在一个矩形区域内,通过盒子的视角更方便的进行页面布局盒子模型组成:内容区域(content&…...
吸猫毛空气净化器哪个好?推荐除猫毛好的宠物空气净化器品牌
如今,越来越多的家庭选择养宠物!虽然家里变得更加温馨,但养宠可能会带来异味和空气中的毛发增多可能会引发健康问题,这也是一个大问题。 但我不想家里到处都是异味,尤其是便便的味道,所以很需要一款能够处…...
为什么你的中文电子书在Calibre中变成了拼音?3个简单步骤彻底解决
为什么你的中文电子书在Calibre中变成了拼音?3个简单步骤彻底解决 【免费下载链接】calibre-do-not-translate-my-path Switch my calibre library from ascii path to plain Unicode path. 将我的书库从拼音目录切换至非纯英文(中文)命名 …...
别再为蓝牙打印头疼了!UniApp + TSC标签打印机保姆级实战(Vue2/Vue3通用)
UniApp蓝牙标签打印实战:从TSC指令集到业务封装的艺术 在移动端开发中,蓝牙打印功能常被视为"技术深水区"——尤其是当业务场景涉及专业标签打印机时。我曾见过不少团队在这个环节耗费数周时间,反复调试却依然面临打印错位、连接不…...
别再只盯着PA效率了!聊聊5G基站功放里那个叫‘记忆效应’的捣蛋鬼
5G基站功放中的记忆效应:从故障排查到工程优化的实战指南 当你在凌晨三点的基站调试现场,面对第17次DPD校准失败告警时,那个隐藏在频谱曲线背后的"时间幽灵"正在嘲笑着所有标准化的线性化方案。记忆效应——这个让功放行为变得&quo…...
Wear OS手表开发避坑:地图应用如何禁用全局滑动返回(附完整style.xml配置)
Wear OS手表开发实战:地图应用中禁用全局滑动返回的深度解决方案 在智能手表的小尺寸屏幕上开发地图导航应用时,最令人头疼的莫过于用户误触侧滑返回手势。想象一下这样的场景:用户正在骑行导航中,手腕自然摆动时不小心触发了返回…...
别再死记硬背公式了!用Python+NumPy手把手带你理解B样条曲线的局部支撑性
用PythonNumPy实战B样条曲线:可视化理解局部支撑性 在汽车设计或游戏建模中,设计师经常需要对曲线进行微调——比如只改动车灯轮廓而不影响车门线条。这种"牵一发而不动全身"的特性,正是B样条曲线被称为"工业建模基石"的…...
颠覆性桌面股票监控:TrafficMonitor插件生态的革命性升级
颠覆性桌面股票监控:TrafficMonitor插件生态的革命性升级 【免费下载链接】TrafficMonitorPlugins 用于TrafficMonitor的插件 项目地址: https://gitcode.com/gh_mirrors/tr/TrafficMonitorPlugins 在信息过载的数字时代,投资者需要一个专注且高效…...
Xray 安全扫描工具详解
介绍 Xray 是由长亭科技推出的免费白帽子工具平台的核心产品,是一款功能强大的安全评估工具,由多名经验丰富的一线安全从业者打造。 🔗 官网: https://xray.cool/ 📦 下载: https://stack.chaitin.com/…...
【AI实战解析】从公式到应用:深入理解三元组损失(Triplet Loss)的优化之道
1. 为什么我们需要三元组损失? 想象一下你在教小朋友认识动物。如果每次只给小朋友看一张猫的图片,然后告诉他"这是猫",他可能很难真正理解猫的特征。但如果你同时展示一张猫(锚点)、另一张猫(正…...
千问3.5-2B多模型对比展示:轻量级2B参数模型的效率与精度平衡
千问3.5-2B多模型对比展示:轻量级2B参数模型的效率与精度平衡 1. 轻量级大模型的独特价值 在AI模型日益庞大的今天,千问3.5-2B作为一款仅20亿参数的轻量级大模型,却在效率与精度之间找到了令人惊喜的平衡点。对于大多数开发者而言ÿ…...
算法训练营第四天|螺旋矩阵
今日学习的文章链接和视频链接: https://www.bilibili.com/video/BV1SL4y1N7mV/ 自己看到题目的第一想法: 第一想法是,先定义矩阵的上下左右四个边界,然后按照从左到右,从上到下,从右到左,从下到…...
