红黑树的C语言简单实现与代码解析

红黑树 C 语言的简单实现与代码解析

红黑树是计算机科学中一种重要的自平衡二叉搜索树。它确保了在最坏情况下,基本的动态集合操作(如插入、删除和查找)具有对数时间复杂度。在这篇博客中,我们将介绍一个简化的C语言红黑树实现,并对代码进行详细解析。

1、示例代码

#include <stdio.h>
#include <stdlib.h>typedef enum { RED, BLACK } color_t;typedef struct Node {int data;color_t color;struct Node *left, *right, *parent;
} Node;typedef struct RedBlackTree {Node *root;
} RedBlackTree;// 创建新节点
Node* createNode(int data) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->data = data;newNode->left = newNode->right = newNode->parent = NULL;newNode->color = RED;  // 默认为红色return newNode;
}// 左旋
void leftRotate(RedBlackTree* tree, Node* x) {Node* y = x->right;x->right = y->left;if (y->left != NULL) y->left->parent = x;y->parent = x->parent;if (x->parent == NULL) tree->root = y;else if (x == x->parent->left) x->parent->left = y;else x->parent->right = y;y->left = x;x->parent = y;
}// 右旋
void rightRotate(RedBlackTree* tree, Node* y) {Node* x = y->left;y->left = x->right;if (x->right != NULL) x->right->parent = y;x->parent = y->parent;if (y->parent == NULL) tree->root = x;else if (y == y->parent->left) y->parent->left = x;else y->parent->right = x;x->right = y;y->parent = x;
}// 插入修复操作
void insertFixup(RedBlackTree* tree, Node* z) {while (z->parent && z->parent->color == RED) {if (z->parent == z->parent->parent->left) {Node* y = z->parent->parent->right;if (y && y->color == RED) {z->parent->color = BLACK;y->color = BLACK;z->parent->parent->color = RED;z = z->parent->parent;} else {if (z == z->parent->right) {z = z->parent;leftRotate(tree, z);}z->parent->color = BLACK;z->parent->parent->color = RED;rightRotate(tree, z->parent->parent);}} else {// 类似地处理右侧情况// ...}}tree->root->color = BLACK;
}// 插入节点
void insert(RedBlackTree* tree, int data) {Node* z = createNode(data);Node* y = NULL;Node* x = tree->root;while (x != NULL) {y = x;if (z->data < x->data) x = x->left;else x = x->right;}z->parent = y;if (y == NULL) tree->root = z;else if (z->data < y->data) y->left = z;else y->right = z;insertFixup(tree, z);
}// 其他操作(如删除、查找等)可以根据上述模式扩展int main() {RedBlackTree tree = {NULL};int arr[] = {7, 3, 18, 10, 22, 8, 11, 26, 2, 6, 13};int n = sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < n; i++) {insert(&tree, arr[i]);}// 执行其他操作或打印树结构return 0;
}

2、代码解析

2.1. 基本结构

我们首先定义了两个基本结构:NodeRedBlackTree

typedef enum { RED, BLACK } color_t;typedef struct Node {int data;color_t color;struct Node *left, *right, *parent;
} Node;typedef struct RedBlackTree {Node *root;
} RedBlackTree;
  • Node 结构包含一个整数数据、一个颜色(红色或黑色)以及左、右子节点和父节点的指针。
  • RedBlackTree 结构只包含一个根节点指针。

2.2 左旋与右旋操作

红黑树的核心操作之一是旋转,这有助于维护树的平衡性。

  • leftRotaterightRotate 函数分别实现了左旋和右旋操作。
2.2 1. 左旋操作

左旋操作是为了将一个节点旋转到其右子节点的位置。这个操作旨在维护红黑树的平衡性。以下是左旋操作的步骤:

  1. 选择节点:假设要进行左旋的节点为 x,并且其右子节点为 y
  2. 更新子节点:将 x 的右子节点 y 的左子节点(y 的左子节点)作为 x 的新右子节点。
  3. 更新父节点:如果 x 有父节点,更新其父节点以指向 y 而不是 x
  4. 更新 y 的左子节点:将 y 的左子节点设置为 x
  5. 更新 x 的父节点:将 y 的父节点设置为 x 的父节点。
2.2.2 右旋操作

右旋操作与左旋相反。它是为了将一个节点旋转到其左子节点的位置。以下是右旋操作的步骤:

右旋步骤:

  1. 选择节点:假设要进行右旋的节点为 y,并且其左子节点为 x
  2. 更新子节点:将 y 的左子节点 x 的右子节点(x 的右子节点)作为 y 的新左子节点。
  3. 更新父节点:如果 y 有父节点,更新其父节点以指向 x 而不是 y
  4. 更新 x 的右子节点:将 x 的右子节点设置为 y
  5. 更新 y 的父节点:将 x 的父节点设置为 y 的父节点。

3. 插入与修复操作

当向红黑树中插入新节点时,可能会破坏红黑树的性质。因此,我们需要进行修复操作。

  • insertFixup 函数实现了在插入后修复红黑树的逻辑。

4. 插入操作

为了简化,我们只展示了如何向红黑树中插入新节点。其他操作(如删除、查找等)可以基于相似的原理进行扩展。

5. 示例

在主函数中,我们展示了如何使用上述功能来创建和填充一个红黑树。

int main() {RedBlackTree tree = {NULL};int arr[] = {7, 3, 18, 10, 22, 8, 11, 26, 2, 6, 13};int n = sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < n; i++) {insert(&tree, arr[i]);}return 0;
}

3、结论

虽然上述代码提供了一个基本的红黑树实现,但实际上红黑树的设计和实现要复杂得多。在实际应用中,需要考虑许多其他细节和情况。然而,通过这个简化的示例,我们可以更好地理解红黑树的基本原理和操作。

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

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

相关文章

mathtype公式章节编号

1. word每章标题后插入章节符 如果插入后显示章节符&#xff0c;需要进行隐藏 开始->样式->MTEquationSection->修改样式->字体&#xff0c;勾选隐藏 2. 设置mathtype公式编号格式 插入编号->格式化->设置格式

test-01-java 单元测试框架 junit 入门介绍

JUnit JUnit 是一个用于编写可重复测试的简单框架。 它是 xUnit 架构的一种实例&#xff0c;专门用于单元测试框架。 What to test? NeedDescRight结果是否正确B边界条件是否满足I能反向关联吗C有其他手段交叉检查吗E是否可以强制异常发生P性能问题 maven 入门例子 maven …

什么是动态代理?

目录 一、为什么需要代理&#xff1f; 二、代理长什么样&#xff1f; 三、Java通过什么来保证代理的样子&#xff1f; 四、动态代理实现案例 五、动态代理在SpringBoot中的应用 导入依赖 数据库表设计 OperateLogEntity实体类 OperateLog枚举 RecordLog注解 上下文相…

SpringMVC基础知识(持续更新中~)

笔记&#xff1a; https://gitee.com/zhengguangqq/ssm-md/blob/master/ssm%20md%E6%A0%BC%E5%BC%8F%E7%AC%94%E8%AE%B0/%E4%B8%89%E3%80%81SpringMVC.md 细节补充&#xff1a;

原地建堆,LeetCode 1962. 移除石子使总数最小

一、题目 1、题目描述 给你一个整数数组 piles &#xff0c;数组 下标从 0 开始 &#xff0c;其中 piles[i] 表示第 i 堆石子中的石子数量。另给你一个整数 k &#xff0c;请你执行下述操作 恰好 k 次&#xff1a; 选出任一石子堆 piles[i] &#xff0c;并从中 移除 floor(pil…

深度学习 | 梯度下降算法及其变体

一、最优化与深度学习 1.1、训练误差与泛化误差 1.2、经验风险 1.3、优化中的挑战 1.3.1、局部最小值 1.3.2、 鞍点 经常是由于模型复杂度过高或者训练样本数据过少造成的 —— Overfitting 1.3.3、悬崖 1.3.4、长期依赖问题 二、损失函数 2.1、损失函数的起源 损失函数(loss…

笔记:一台电脑如何安装多个不同版本的Node并能自由切换(NVM)

前言&#xff1a;相信大家在做前端开发时公司有vue2和vue3的项目需要维护或自学&#xff0c;vue2大多只需要Node 14版本&#xff0c;而vue3则是16或18&#xff0c;但电脑只能装一个Node&#xff0c;可我全都要。比如一会切到Node14 vue2开发&#xff0c;一会切到Node 16或18 vu…

041_小驰私房菜_MTK平台添加支持通过原生Camera API接口调用UsbCamera

平台:MTK 问题:通过调用Android Camera API去调用UsbCamera,需要做哪些修改? Google官方文档,关于usbcamera的支持: 外接 USB 摄像头 | Android 开源项目 | Android Open Source Project 相关修改内容如下: 一、MTK平台支持通过标准接口打开USB Camera 1)device相…

每日一题——轮转数组

1. 题目描述 给定一个整数数组nums&#xff0c;将数组中的元素向右轮转k个位置&#xff0c;其中k是非负数。 示例1: 输入&#xff1a;nums [1,2,3,4,5,6,7]&#xff0c;k 3 输出&#xff1a;[5,6,7,1,2,3,4] 解释&#xff1a; 向右轮转 1步&#xff1a;[7,1,2,3,4,5,6] 向右…

Unity自带的NavMesh寻路组件

最近看了一下Unity自带的NavMesh寻路组件&#xff0c;先说一下基本的使用&#xff1a; 首先先把AI Navgation的package包给安装上。 给场景地图添加上NavMeshSurface组件&#xff0c;然后进行烘焙&#xff0c;烘焙出对应的场景地图文件。 给移动物体添加对应的Nav MeshAgent组…

Nodejs+Express搭建HTTPS服务

最近开发需要搭建一个https的服务&#xff0c;正好最近在用nodejs和express&#xff0c;于是乎想到就近就使用这两东西来搭建一个https的服务吧。这里搭建过程总共需要两步&#xff0c;第一步生成证书&#xff0c;第二步使用https模块启动服务。 生成自签名证书 这里因为是自…

【XML】TinyXML 详解(二):接口详解

【C】郭老二博文之&#xff1a;C目录 1、XML测试文件&#xff08;laoer.xml&#xff09; <?xml version"1.0" standalone"no" ?> <!-- Hello World !--> <root><child name"childName" id"1"><c_child…

【蓝桥杯备考】第十一届蓝桥杯省赛Java B组真题编程题

第十二届蓝桥杯省赛Java B组真题 编程题 1. 杨辉三角问题描述 2. 时间显示问题描述 3. 双向排序问题描述 4. 括号序列问题描述分析 5.砝码称重分析 1. 杨辉三角 问题描述 著名的杨辉三角形&#xff0c;按从上到下、从左到右的顺序把所有数排成一列&#xff0c;可以得到如下数…

可视化开发

可视化开发 数据可视化 交互式可视化 文章目录 可视化开发前言一、可视化开发二、Python数据可视化大屏GIS图像智能识别处理软件开发三、可视化开发必备总结前言 可视化开发可以帮助开发者通过图形化界面和拖放操作来创建、编辑和测试应用程序。使用这些工具,开发者可以提高开…

解决用Fiddler抓包,网页显示你的连接不是专用/私密连接

关键&#xff1a;重置fiddler的证书 在Fiddler重置证书 1、Actions --> Reset All Certificates --> 弹窗一路yes 2、关掉Fiddler&#xff0c;重新打开 3、手机删掉证书&#xff0c;重新下载安装。 &#xff08;如果还不行&#xff0c;重新试一遍&#xff0c;先把浏览器…

1223西站坐标更新

1223 西站坐标更新 1.Update for the station’s location def initial_out_map_indoor_points(self):Load the indoor data and update both the wall_matrix and the ditch_matrix.# Initialize the wall_matrix# List of coordinatescoordinates [(417, 287, 417, 290),(4…

CSS3新增特性

CSS3 CSS3私有前缀 W3C 标准所提出的某个CSS 特性&#xff0c;在被浏览器正式支持之前&#xff0c;浏览器厂商会根据浏览器的内核&#xff0c;使用私有前缀来测试该 CSS 特性&#xff0c;在浏览器正式支持该 CSS 特性后&#xff0c;就不需要私有前缀了。 查询 CSS3 兼容性的网…

非静压模型NHWAVE学习(14)—— 算例制作:开闸式异重流(lock-exchange flow)

NHWAVE学习—— 算例制作&#xff1a;开闸式异重流&#xff08;lock-exchange flow&#xff09; 算例简介模型配置代码修改及输入文件制作代码修改参数文件制作&#xff08;input.txt&#xff09;水深和初始密度场文件制作&#xff08;depth.txt & sali0.txt&#xff09; 模…

【tcmalloc】优化方法

一.脱离new使用定长内存池 此项目本意是脱离malloc的使用&#xff0c;但若使用new的话仍然会使用到malloc。因为centralcache和pagecache本身是单例&#xff0c;不考虑创建对象的问题&#xff0c;但是每个线程自身拥有个线程缓冲区和span结构是要考虑new的问题的&#xff0c;引…

springboot实现发送邮件开箱即用

springboot实现发送邮件开箱即用 环境依赖包yml配置Service层Controller层测试 环境 jdk17 springboot版本3.2.1 依赖包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId><ver…