/*-----------------------------------------------------------
RB-Tree的插入和删除操作的实现算法
参考资料:
1) <<Introduction to algorithm>>
2) http://lxr.linux.no/linux/lib/rbtree.c
作者:http://www.cppblog.com/converse/
您可以自由的传播,修改这份代码,转载处请注明原作者
红黑树的几个性质:
1) 每个结点只有红和黑两种颜色
2) 根结点是黑色的
3)空节点是黑色的(红黑树中,根节点的parent以及所有叶节点lchild、rchild都不指向NULL,而是指向一个定义好的空节点)。
4) 如果一个结点是红色的,那么它的左右两个子结点的颜色是黑色的
5) 对于每个结点而言,从这个结点到叶子结点的任何路径上的黑色结点
的数目相同
-------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef int key_t;
typedef int data_t;
typedef enum color_t
{
RED = 0,
BLACK = 1
}color_t;
typedef struct rb_node_t
{
struct rb_node_t *left, *right, *parent;
key_t key;
data_t data;
color_t color;
}rb_node_t;
/* forward declaration */
rb_node_t* rb_insert(key_t key, data_t data, rb_node_t* root);
rb_node_t* rb_search(key_t key, rb_node_t* root);
rb_node_t* rb_erase(key_t key, rb_node_t* root);
int main()
{
int i, count = 900000;
key_t key;
rb_node_t* root = NULL, *node = NULL;
srand(time(NULL));
for (i = 1; i < count; ++i)
{
key = rand() % count;
if ((root = rb_insert(key, i, root)))
{
printf("[i = %d] insert key %d success!\n", i, key);
}
else
{
printf("[i = %d] insert key %d error!\n", i, key);
exit(-1);
}
if ((node = rb_search(key, root)))
{
printf("[i = %d] search key %d success!\n", i, key);
}
else
{
printf("[i = %d] search key %d error!\n", i, key);
exit(-1);
}
if (!(i % 10))
{
if ((root = rb_erase(key, root)))
{
printf("[i = %d] erase key %d success\n", i, key);
}
else
{
printf("[i = %d] erase key %d error\n", i, key);
}
}
}
return 0;
}
static rb_node_t* rb_new_node(key_t key, data_t data)
{
rb_node_t *node = (rb_node_t*)malloc(sizeof(rb_node_t));
if (!node)
{
printf("malloc error!\n");
exit(-1);
}
node->key = key, node->data = data;
return node;
}
/*-----------------------------------------------------------
| node right
| / \ ==> / \
| a right node y
| / \ / \
| b y a b
-----------------------------------------------------------*/
static rb_node_t* rb_rotate_left(rb_node_t* node, rb_node_t* root)
{
rb_node_t* right = node->right;
if ((node->right = right->left))
{
right->left->parent = node;
}
right->left = node;
if ((right->parent = node->parent))
{
if (node == node->parent->right)
{
node->parent->right = right;
}
else
{
node->parent->left = right;
}
}
else
{
root = right;
}
node->parent = right;
return root;
}
/*-----------------------------------------------------------
| node left
| / \ / \
| left y ==> a node
| / \ / \
| a b b y
-----------------------------------------------------------*/
static rb_node_t* rb_rotate_right(rb_node_t* node, rb_node_t* root)
{
rb_node_t* left = node->left;
if ((node->left = left->right))
{
left->right->parent = node;
}
left->right = node;
if ((left->parent = node->parent))
{
if (node == node->parent->right)
{
node->parent->right = left;
}
else
{
node->parent->left = left;
}
}
else
{
root = left;
}
node->parent = left;
return root;
}
static rb_node_t* rb_insert_rebalance(rb_node_t *node, rb_node_t *root)
{
rb_node_t *parent, *gparent, *uncle, *tmp;
while ((parent = node->parent) && parent->color == RED)
{
gparent = parent->parent;
if (parent == gparent->left)
{
uncle = gparent->right;
if (uncle && uncle->color == RED)
{
uncle->color = BLACK;
parent->color = BLACK;
gparent->color = RED;
node = gparent;
}
else
{
if (parent->right == node)
{
root = rb_rotate_left(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
parent->color = BLACK;
gparent->color = RED;
root = rb_rotate_right(gparent, root);
}
}
else
{
uncle = gparent->left;
if (uncle && uncle->color == RED)
{
uncle->color = BLACK;
parent->color = BLACK;
gparent->color = RED;
node = gparent;
}
else
{
if (parent->left == node)
{
root = rb_rotate_right(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
parent->color = BLACK;
gparent->color = RED;
root = rb_rotate_left(gparent, root);
}
}
}
root->color = BLACK;
return root;
}
static rb_node_t* rb_erase_rebalance(rb_node_t *node, rb_node_t *parent, rb_node_t *root)
{
rb_node_t *other, *o_left, *o_right;
while ((!node || node->color == BLACK) && node != root)
{
if (parent->left == node)
{
other = parent->right;
if (other->color == RED)
{
other->color = BLACK;
parent->color = RED;
root = rb_rotate_left(parent, root);
other = parent->right;
}
if ((!other->left || other->left->color == BLACK) &&
(!other->right || other->right->color == BLACK))
{
other->color = RED;
node = parent;
parent = node->parent;
}
else
{
if (!other->right || other->right->color == BLACK)
{
if ((o_left = other->left))
{
o_left->color = BLACK;
}
other->color = RED;
root = rb_rotate_right(other, root);
other = parent->right;
}
other->color = parent->color;
parent->color = BLACK;
if (other->right)
{
other->right->color = BLACK;
}
root = rb_rotate_left(parent, root);
node = root;
break;
}
}
else
{
other = parent->left;
if (other->color == RED)
{
other->color = BLACK;
parent->color = RED;
root = rb_rotate_right(parent, root);
other = parent->left;
}
if ((!other->left || other->left->color == BLACK) &&
(!other->right || other->right->color == BLACK))
{
other->color = RED;
node = parent;
parent = node->parent;
}
else
{
if (!other->left || other->left->color == BLACK)
{
if ((o_right = other->right))
{
o_right->color = BLACK;
}
other->color = RED;
root = rb_rotate_left(other, root);
other = parent->left;
}
other->color = parent->color;
parent->color = BLACK;
if (other->left)
{
other->left->color = BLACK;
}
root = rb_rotate_right(parent, root);
node = root;
break;
}
}
}
if (node)
{
node->color = BLACK;
}
return root;
}
static rb_node_t* rb_search_auxiliary(key_t key, rb_node_t* root, rb_node_t** save)
{
rb_node_t *node = root, *parent = NULL;
int ret;
while (node)
{
parent = node;
ret = node->key - key;
if (0 < ret)
{
node = node->left;
}
else if (0 > ret)
{
node = node->right;
}
else
{
return node;
}
}
if (save)
{
*save = parent;
}
return NULL;
}
rb_node_t* rb_insert(key_t key, data_t data, rb_node_t* root)
{
rb_node_t *parent = NULL, *node;
parent = NULL;
if ((node = rb_search_auxiliary(key, root, &parent)))
{
return root;
}
node = rb_new_node(key, data);
node->parent = parent;
node->left = node->right = NULL;
node->color = RED;
if (parent)
{
if (parent->key > key)
{
parent->left = node;
}
else
{
parent->right = node;
}
}
else
{
root = node;
}
return rb_insert_rebalance(node, root);
}
rb_node_t* rb_search(key_t key, rb_node_t* root)
{
return rb_search_auxiliary(key, root, NULL);
}
rb_node_t* rb_erase(key_t key, rb_node_t *root)
{
rb_node_t *child, *parent, *old, *left, *node;
color_t color;
if (!(node = rb_search_auxiliary(key, root, NULL)))
{
printf("key %d is not exist!\n");
return root;
}
old = node;
if (node->left && node->right)
{
node = node->right;
while ((left = node->left) != NULL)
{
node = left;
}
child = node->right;
parent = node->parent;
color = node->color;
if (child)
{
child->parent = parent;
}
if (parent)
{
if (parent->left == node)
{
parent->left = child;
}
else
{
parent->right = child;
}
}
else
{
root = child;
}
if (node->parent == old)
{
parent = node;
}
node->parent = old->parent;
node->color = old->color;
node->right = old->right;
node->left = old->left;
if (old->parent)
{
if (old->parent->left == old)
{
old->parent->left = node;
}
else
{
old->parent->right = node;
}
}
else
{
root = node;
}
old->left->parent = node;
if (old->right)
{
old->right->parent = node;
}
}
else
{
if (!node->left)
{
child = node->right;
}
else if (!node->right)
{
child = node->left;
}
parent = node->parent;
color = node->color;
if (child)
{
child->parent = parent;
}
if (parent)
{
if (parent->left == node)
{
parent->left = child;
}
else
{
parent->right = child;
}
}
else
{
root = child;
}
}
free(old);
if (color == BLACK)
{
root = rb_erase_rebalance(child, parent, root);
}
return root;
}相关推荐
从零开始:H20服务器上DeepSeek R1 671B大模型部署与压力测试全攻略
最近,我有幸在工作中接触到了DeepSeek R1 671B模型,这是目前中文开源领域参数量最大的高质量模型之一。DeepSeek团队在2024年推出的这款模型,以其惊人的6710亿参数量和出色的推理性能,引起了业界广泛关注。作为一名AI基础设施工程师,我有机会在H20服务器上部署这个庞然大物,并对其进行了全面的压力测试。这篇文章将详细记录我的部署过程和性能测试方法,希望能为大家提供一些参考。💡为什么选择DeepSeek R1?超大规模参数量(671B)优秀的中英文理解能力开源可商用的许可证。
Sanity Testing 和 Smoke Testing的区别
Sanity Testing 和 Smoke Testing的区别 Sanity testing 和Smoke Testing是两个非常容易混淆的测试类型。 Smoke Testing(冒烟测试) Smoke Testing(冒烟测试)是在软件构建(build)后进行的一种测试,用来确定程序的关键功能是否正常工作。在软件构建上执行任何详细的功能或回归测试之前执行。目的是拒绝一个严重损坏的应用...
Pixhawk+OpenMV实战:如何用Apriltag实现无人机自动降落(附避坑指南)
本文详细介绍了如何利用Pixhawk飞控和OpenMV摄像头,通过Apriltag视觉标签实现无人机的精准降落系统。从硬件搭建、参数配置到视觉处理代码优化,提供了完整的实战指南和避坑建议,帮助开发者快速实现厘米级精度的自动降落功能。
从querySelector到testing-library:Testing Playground帮你选择最佳查询方式
Testing Playground是一个简单而完整的DOM测试工具,它能帮助开发者从传统的querySelector方法平滑过渡到更符合可访问性标准的testing-library查询方式,从而鼓励良好的测试实践。无论是前端新手还是有经验的开发者,都能通过这个工具提升DOM元素查询的准确性和测试代码的可维护性。 ## 🧩 为什么需要测试查询优化工具? 在前端测试中,选择正确的DOM元素查询
STM32F103C8T6蓝莓派用HAL库GPIO模拟SPI驱动MAX31865读取PT100温度(附完整代码)
本文详细介绍了如何在STM32F103C8T6蓝莓派开发板上使用HAL库通过GPIO模拟SPI驱动MAX31865读取PT100温度传感器的完整方案。内容包括硬件连接、CubeMX配置、GPIO模拟SPI实现、温度计算算法及常见问题排查,并附有完整代码示例,帮助开发者快速实现高精度温度测量。
Oracle EBS R12.2 安装 -- Step by Step
Oracle EBS R12.2 安装 -- Step by Step
Go 单元测试 testing 包详解(testing.T、M、B、PB)
单元测试(Unit Testing)是指对软件中的最小可测试单元(通常是函数、方法或类)进行验证,以确保其行为符合预期;是开发人员开发中、需求交付前必备的一项工作Go 内置了轻量级的测试框架,通过标准库testing提供支持,无需额外依赖。
JLink版本不兼容?手把手教你解决APM32F003F6P6在Keil中烧写闪退和报错
本文详细解析了APM32F003F6P6在Keil中烧写闪退和报错的解决方案,重点介绍了JLink版本兼容性问题。通过实测不同版本组合,推荐使用JLink 7.20a或6.86b与Keil 5.25的黄金组合,并提供详细的降级驱动和工程配置步骤,帮助开发者高效解决烧写困境。
testing123
testing 123
nvidia系列教程-AGX-Orin基础环境搭建
NVIDIA Jetson AGX Orin 是一款功能强大的嵌入式AI平台,专为需要高性能和低功耗的边缘计算应用设计。无论是自动驾驶、机器人,还是智能监控系统,Jetson AGX Orin 都能为这些应用提供强大的计算能力。本篇博客将为大家详细介绍如何在AGX Orin(32GB)上搭建基础开发环境,包括系统安装、CUDA和cuDNN的配置等,帮助你快速上手这个强大的平台。架构: 搭载 56 个 Tensor Core 的 1792 核 NVIDIA Ampere c GPUCUDA Cores。
使用YOLOv5进行工业检测(如裂纹、划痕、破损等)
本文将详细介绍如何使用YOLOv5实现工业检测项目,以检测生产线上的缺陷产品,如裂纹、划痕、破损等。我们将分步介绍数据准备、模型训练、模型优化和部署等过程。
udemy-TESTING-LIBRARY:助力React组件测试,提升开发效率
udemy-TESTING-LIBRARY:助力React组件测试,提升开发效率 在当今前端开发领域,React无疑是最受欢迎的JavaScript库之一。然而,随着项目规模的扩大,组件数量的增加,如何保证组件的质量和稳定性成为了开发者们关注的焦点。udemy-TESTING-LIBRARY正是为了解决这一问题而诞生的开源项目。 项目介绍 udemy-TESTING-LIBRARY是一个与Udem...
【华为OD机试真题】45、 分糖果 | 机试真题+思路参考+代码解析(C++、Java、Py、JS)
### 🎃题目描述 >小明从糖果盒中随意抓一把糖果,每次小明会取出一半的糖果分给同学们。 > 当糖果不能平均分配时,小明可以选择从糖果盒中(假设盒中糖果足够)取出一个糖果或放回一个糖果。 > 小明最少需要多少次(取出、放回和平均分配均记一次),能将手中糖果分至只剩一颗。
【亲测免费】 Testing Playground 使用教程
Testing Playground 是一个用于辅助开发者编写和调试前端测试用例的开源工具。它通过提供一个交互式的界面,帮助开发者理解和优化他们的测试代码。Testing Playground 主要针对使用 React Testing Library 和其他类似的测试库的开发者,旨在简化测试用例的编写过程,提高测试代码的可读性和可维护性。 ## 项目快速启动 ### 安装 首先,你需要在你的...
NTscan扫描工具
ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。
android 蓝牙通讯demo
android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。
Testing Playground源码解析:核心组件queryAdvise的实现原理
Testing Playground是一个简单而完整的DOM测试工具,旨在鼓励良好的测试实践。其中queryAdvise组件作为核心功能模块,负责为开发者提供智能的DOM元素查询建议,帮助编写更健壮、可维护的测试代码。本文将深入解析queryAdvise组件的实现原理,揭示其如何通过多种策略生成精准的查询建议。 ## queryAdvise组件的核心功能与价值 在DOM测试中,选择合适的元素查
win10 跳过U8环境检测的IE WebControls.rar
win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。
AI时代测试方向AI for Testing和Testing for AI
AI环境下的测试行业发展方向
精雕软件(JDpaint) 5.5 绿色版
精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版
Vue Testing Library 使用教程
Vue Testing Library 是一个轻量级的适配器,构建在 DOM Testing Library 和 @vue/test-utils 之上。它提供了一系列的测试工具,旨在鼓励良好的测试实践,使你的测试尽可能地模拟用户与 Vue 组件的交互。 ## 项目快速启动 ### 安装 首先,你需要通过 npm 安装 Vue Testing Library: ```bash npm ins...
对于多因子组合测试工具pairwise testing及PICT的探索总结
对于多因子组合测试工具pairwise testing及PICT的探索 一、简介 对于存在多个输入参数,例如多个条件的筛选,每个条件中又有多个选项让我们选择,如果全部覆盖的话,那数量级必然是相当大的。 而pairwise testing 即配对测试是一种行之有效的简化此类测试用例的思路,它的理论基础是统计分析及正交分析; 它基于以下两个两个原则: 1.每一个维度都是正交的,即每一个维度互相都没有交集。 2.根据数学统计分析,73%的缺陷(单因子是35%,双因子是38%)是由单因子或2个因子相互作用产生的。1
gopter vs ScalaCheck vs testing/quick:一页讲透 Go 性质测试选型
**gopter**(GOlang Property TestER)是 Go 语言中功能最完整的性质测试(Property-Based Testing)框架,也是 `testing/quick` 的进阶替代方案。本文一页对比 gopter、ScalaCheck、Go 标准库 `testing/quick` 三者的核心差异,帮新手快速完成 Go 性质测试选型。 ## 🎯 什么是性质测试:一次说清
探索 Testing-Playground:您的DOM测试新伙伴
在软件开发的复杂世界中,测试是确保代码质量和稳定性的关键步骤。今天,我们将介绍一个强大的工具——**Testing-Playground**,这是一个简单而完整的DOM测试环境,旨在鼓励和促进良好的测试实践。 ## 项目介绍 **Testing-Playground** 是一个专为 [testing-library/dom](https://github.com/testing-library...
MCreator 音乐唱片时长(music disc length in ticks)参数完全指南:单位换算、悦灵停止跳舞机制与源码实现
本文是 MCreator 物品编辑器中"音乐唱片时长(Music length in ticks)"参数的实战指南。该参数用于定义自定义音乐唱片在唱片机(Jukebox)中播放的总时长,并控制悦灵(Allay)在音乐结束时停止跳舞的行为。读完本文,你将掌握该参数的 tick 单位换算规则、合法取值范围与默认值、底层生成逻辑,并能结合源码理解它在 NeoForge 数据包中的落地方式。 ## 参数
React Testing完全指南:Jest、React Testing Library实战
本文全面介绍了使用Jest和React Testing Library进行React应用测试的完整方案。主要内容包括:测试类型与基础概念、Jest框架特性、React Testing Library的核心原则与查询方法、环境搭建指南,以及从基础组件测试到复杂交互测试的实战演示。文章重点讲解了异步操作测试、Mock/Spy技术、自定义Hook测试和集成测试等高级主题,并提供了测试最佳实践建议,帮助开发者构建可靠的测试体系,确保应用质量。
Testing Playground完全指南:从0到1掌握DOM测试的终极工具
Testing Playground是一个简单而完整的DOM测试 playground,旨在鼓励良好的测试实践。它为开发者提供直接的反馈,帮助可视化添加和删除特定(aria)属性的直接影响,提供视觉支持以学习aria角色、标签和属性的重要性。 ## 为什么选择Testing Playground? 对于许多开发者来说,即使使用Testing-Library,找到正确的查询或理解元素未被匹配的原
如何用react-native-testing测试登录表单?完整提交流程实战
react-native-testing是一个专注于React Native组件测试的工具集,结合Jest和React Native Testing Library,能够帮助开发者高效验证登录表单等交互组件的功能完整性。本文将通过实战案例,带你掌握登录表单的测试方法和提交流程验证技巧。 ## 为什么要测试登录表单? 登录表单作为用户进入应用的第一道关卡,其功能稳定性直接影响用户体验。通过rea
知识点滴 - Test和Testing的区别
testing:不可数名词。测试是指为了发现信息而对某物或某人进行测试的活动。"testing"是指一般的活动,而 "test"是指这个活动中的每一个小动作。test:可数名词。测试是一种刻意的行动或实验,以了解某物的运作情况。
Cypress Testing Library 项目常见问题解决方案
Cypress Testing Library 是一个开源项目,旨在为使用 Cypress 测试框架的开发者提供简单且完整的自定义命令和工具,以促进良好的测试实践。该项目主要使用 JavaScript 编程语言,并且与 Cypress 和 DOM Testing Library 深度集成,帮助开发者更轻松地编写端到端的测试。 ## 新手常见问题及解决步骤 ### 问题一:如何安装 Cypres...
1万+



被折叠的 条评论
为什么被折叠?



