开源C语言库Melon:红黑树

本文对Melon库中的红黑树进行介绍,关于Melon库,这是一个开源的C语言库,它具有:开箱即用、无第三方依赖、安装部署简单、中英文文档齐全等优势。

Github repo

在这里插入图片描述

简介

红黑树是一种被应用的非常广泛的数据结构,用于快速搜索指定数据集中的数据。

这里我们不对红黑树的原理进行展开,仅给出其时间复杂度和使用场景介绍。

时间复杂度

  • 插入:O(logN)
  • 删除:O(logN)
  • 搜索:O(logN)

使用场景

  • 实现字典查询,即kv查询
  • 文件描述符索引,例如维护socket fd

使用

Melon库中的红黑树经历了若干次迭代,最终形成了当前的使用形态。我们先给出代码,再进而说明为何会演变至此。

红黑树

#include <stdio.h>
#include <stdlib.h>
#include "mln_core.h"
#include "mln_log.h"
#include "mln_rbtree.h"static int cmp_handler(const void *data1, const void *data2)
{return *(int *)data1 - *(int *)data2;
}int main(int argc, char *argv[])
{int n = 10;mln_rbtree_t *t;mln_rbtree_node_t *rn;struct mln_rbtree_attr rbattr;struct mln_core_attr cattr;cattr.argc = argc;cattr.argv = argv;cattr.global_init = NULL;cattr.master_process = NULL;cattr.worker_process = NULL;if (mln_core_init(&cattr) < 0) {fprintf(stderr, "init failed\n");return -1;}rbattr.pool = NULL;rbattr.pool_alloc = NULL;rbattr.pool_free = NULL;rbattr.cmp = cmp_handler;rbattr.data_free = NULL;rbattr.cache = 0;if ((t = mln_rbtree_new(&rbattr)) == NULL) {mln_log(error, "rbtree init failed.\n");return -1;}rn = mln_rbtree_node_new(t, &n);if (rn == NULL) {mln_log(error, "rbtree node init failed.\n");return -1;}mln_rbtree_insert(t, rn);rn = mln_rbtree_root_search(t, &n);if (mln_rbtree_null(rn, t)) {mln_log(error, "node not found\n");return -1;}mln_log(debug, "%d\n", *((int *)mln_rbtree_node_data(rn)));mln_rbtree_delete(t, rn);mln_rbtree_node_free(t, rn);mln_rbtree_free(t);return 0;
}

main函数大致流程如下:

  1. 定义变量
  2. 初始化Melon库
  3. 设置红黑树初始化属性
  4. 创建红黑树
  5. 创建红黑树结点
  6. 插入结点
  7. 搜索结点
  8. 删除结点
  9. 销毁结点
  10. 销毁红黑树结构

Melon中,使用红黑树需要引入mln_rbtree.h头文件。

这里我们需要对红黑树初始化属性进行一番说明,这也是演变至今逐渐变复杂的地方。

struct mln_rbtree_attr {void                      *pool;rbtree_pool_alloc_handler  pool_alloc;rbtree_pool_free_handler   pool_free;rbtree_cmp                 cmp;rbtree_free_data           data_free;
};
typedef void *(*rbtree_pool_alloc_handler)(void *, mln_size_t);
typedef void (*rbtree_pool_free_handler)(void *);
typedef int (*rbtree_cmp)(const void *, const void *);
typedef void (*rbtree_free_data)(void *);

其中:

  • pool是用于支持用户自定义内存池之用的,该指针将于pool_allocpool_free配合使用。
  • pool_alloc是用于支持用户自定义分配内存之用,该函数指针第一个参数为pool,第二个参数是要分配的内存大小。
  • pool_free是用于支持用户自定义释放内存之用,该函数指针第一个参数为要释放的内存起始地址。
  • cmp是用于对两个树结点所关联的用户自定义数据进行比较大小之用的。
  • data_free是用于对红黑树结点所关联的用户自定义数据进行释放之用的。

这些指针,若无需要可以置NULL

内存池和分配释放函数主要是用于树结点的分配和释放之用。之所以不直接给出一个Melon实现的内存池结构指针,是因为不希望红黑树代码与内存池类型强关联,这样允许红黑树可以接入使用者自己定义的内存管理功能。

演化

早期,红黑树只有cmpdata_free。后来加入了poolpool_allocpool_free来增加内存分配来源。

从14年至今的使用中,会不断遇到新的使用场景,因此对红黑树内部结构做各种调整,例如:

  • 遍历红黑树所有结点
  • 遍历红黑树所有结点的同时删除其中的结点
  • 增加结点计数

因此,如果读者阅读源码,会发现树结构中还有一个双向链表结构用来辅助结点遍历。

可能有的读者会提出,为什么树结点不能与关联的自定义数据结构一同分配,类似如下代码:

struct some_struct {int val;...mln_rbtree_node_t node;
}void some_function(...)
{struct some_struct *s;mln_rbtree_t *tree;s = malloc(...);//allocate struct some_structmln_rbtree_node_init(&s->node, s);...mln_rbtree_insert(tree, &s->node);...
}

这段代码不能真实执行。

之所以不这样设计,并非没有设想和尝试过。但是发现如此设计存在一下优劣势:

  • 优势:少了一次树结点内存分配动作
  • 劣势:如果结点要加入多个树结构,则需要在结构体中给出多个node成员,若并不一定每一个树结构都加入,则会造成一定的内存浪费。且后续功能扩展时引入了红黑树结构,也有可能要给很多结构体中引入node结点,才能完成红黑树的功能,这增加了二开的成本。

结语

Melon中的红黑树目前演化至此,相信也不会是其最终形态。也希望广大开发者朋友提出宝贵意见和建议。

另外对于Melon库感兴趣的读者,可以访问Github仓库。

感谢阅读!

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

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

相关文章

Veeam Backup12安装备份恢复ESXI7.0 U3虚拟机

介绍 只需单个平台即可保护并管理所有工作负载、应用及数据&#xff1a;云端、虚拟、物理、SaaS、Kubernetes、VMware、Hyper-V、Windows、Linux、UNIX、NAS、AWS、Azure、企业应用等。 个人主要用于备份ESXi上的虚拟机&#xff0c;可以实现单次完整备份&#xff0c;和定时的…

Vue3 的基本开发+新特性

Vue3 1.Vue3 1. Vue2 选项式 API vs Vue3 组合式API <script> export default {data(){return {count:0}},methods:{addCount(){this.count}} } </script> <script setup> import { ref } from vue const count ref(0) const addCount ()> count.val…

小H靶场笔记:Empire-Breakout

Empire&#xff1a;Breakout January 11, 2024 11:54 AM Tags&#xff1a;brainfuck编码&#xff1b;tar解压变更目录权限&#xff1b;Webmin&#xff1b;Usermin Owner&#xff1a;只惠摸鱼 信息收集 使用arp-scan和namp扫描C段存活主机&#xff0c;探测靶机ip&#xff1a;1…

作业--day45

定时播放 #include "mywidget.h" #include "ui_mywidget.h"MyWidget::MyWidget(QWidget *parent) :QWidget(parent),ui(new Ui::MyWidget) {ui->setupUi(this);ui->bg_lab->setPixmap(QPixmap(":/pictrue/shanChuan.jpg"));ui->bg_…

AJAX入门到实战,学习前端框架前必会的(ajax+node.js+webpack+git)(六)

《诗小雅小旻》&#xff1a;“战战兢兢&#xff0c;如临深渊&#xff0c;如履薄冰。” 01.Nodejs安装与使用 什么是 Node.js&#xff1f; 什么是前端工程化&#xff1f; Node.js 为何能执行 JS&#xff1f; 查看当前使用的Node.js版本&#xff1a;node -v 执行JS&#xff1a;no…

Linux(Debina12)系统安装

在开发或学习中&#xff0c;linux系统是我们必须要熟悉的系统&#xff0c;那么今天就记录一下&#xff0c;较为稳定&#xff0c;也是小编这几年当做开发环境的发行版吧 官网地址 https://www.debian.org 下载链接 http://mirrors.163.com/debian-cd/12.4.0/amd64/iso-dvd/ …

先锋WEB燃气收费系统 Upload.aspx 文件上传漏洞复现

0x01 产品简介 先锋WEB燃气收费系统是一种先进的在线燃气收费解决方案,旨在简化和优化燃气收费的流程和管理。该系统基于Web平台,提供了一系列功能和工具,使燃气公司能够高效地进行收费、账单管理和客户服务。 0x02 漏洞概述 先锋WEB燃气收费系统/AjaxService/Upload.asp…

PHP版学校教务管理系统源码带文字安装教程

PHP版学校教务管理系统源码带文字安装教程 运行环境 服务器宝塔面板 PHP 7.0 Mysql 5.5及以上版本 Linux Centos7以上 系统介绍&#xff1a; 后台权限控制&#xff1a;支持多个管理员&#xff0c;学生管理&#xff0c;学生成绩&#xff0c;教师管理&#xff0c;文章管理&#x…

随机漫步【scatter的使用】

去掉scatter的坐标轴&#xff08;未成功版&#xff09; import matplotlib.pyplot as plt from random import choice class RandomWalk():def __init__(self,num_points 5000):self.num_points num_pointsself.x_values [0]self.y_values [0]def fill_walk(self):while l…

实现秒杀功能设计

页面 登录页面 登录成功后&#xff0c;跳转商品列表 商品列表页 加载商品信息 商品详情页 根据商品id查出商品信息返回VO&#xff08;包括rmiaoshaStatus、emainSeconds&#xff09;前端根据数据展示秒杀按钮&#xff0c;点击开始秒杀 订单详情页 秒杀页面设置 后端返回秒杀…

Pycharm close project 速度缓慢解决办法

解决Pycharm close project缓慢现象 1.问题描述 close project后需要等待很长的时间。 2.解决办法 在Help -> Find Action -> 输入 Registry -> 禁用ide.await.scope.completion 问题解决&#xff01;&#xff01;&#xff01; &#x1f603;&#x1f603;&#x…

LeetCode+ 56 - 60

合并区间 双指针算法、位运算、离散化、区间合并_小雪菜本菜的博客-CSDN博客 class Solution { public:vector<vector<int>> merge(vector<vector<int>>& a) {vector<vector<int>> res;if(a.empty()) return res;sort(a.begin(),a.en…

Android开发基础(四)

Android开发基础&#xff08;四&#xff09; 本篇将从Android数据存储方式去理解Android开发。 Android数据存储方式 Android提供了多种数据存储方式。 一、SharedPreferences存储 主要用于存储一些简单的配置信息&#xff0c;如登录账号密码等&#xff1b; 这种存储方式采…

U盘启动安装win11遇到缺少计算机所需的介质驱动程序问题

一、使用U盘制作启动盘遇到问题 下载了windows原版镜像&#xff0c;验证了md5&#xff0c;确保文件没有损坏。使用ultroiso制作u盘启动盘&#xff0c;开始安装后出现下图的报错&#xff1a; 在网上搜索解决方案&#xff0c;主要有以下几种&#xff1a; 安装的时候&#xff0c…

MySQL 8.0 InnoDB Tablespaces之Temporary Tablespaces(临时表空间)

文章目录 MySQL 8.0 InnoDB Tablespaces之Temporary Tablespaces&#xff08;临时表空间&#xff09;会话临时表空间会话临时表空间的磁盘分配和回收会话临时表空间的创建创建临时表和查看临时表信息会话临时表空间相关的设置参数innodb_temp_tablespaces_dir 全局临时表空间查…

leetcode 每日一题 2024年01月09日 字符串中的额外字符

题目 字符串中的额外字符 给你一个下标从 0 开始的字符串 s 和一个单词字典 dictionary 。你需要将 s 分割成若干个 互不重叠 的子字符串&#xff0c;每个子字符串都在 dictionary 中出现过。s 中可能会有一些 额外的字符 不在任何子字符串中。 请你采取最优策略分割 s &…

Tensorflow2.0笔记 - 修改形状和维度

本次笔记主要使用reshape&#xff0c;transpose&#xff0c;expand_dim&#xff0c;和squeeze对tensor的形状和维度进行操作。 import tensorflow as tf import numpy as nptf.__version__#tensor的shape和维数获取 #假设下面这个tensor表示4张28*28*3的图片 tensor tf.rando…

延时任务的解决方案

延时任务的解决方案 1.数据库轮询2. JDK的延迟队列3.netty时间轮算法4.使用消息队列 1.数据库轮询 该方案通常是在小型项目中使用&#xff0c;即通过一个线程定时的去扫描数据库&#xff0c;通过订单时间来判断是否有超时的订单&#xff0c;然后进行update或delete等操作 代码示…

C++核心编程——类和对象(二)

本专栏记录C学习过程包括C基础以及数据结构和算法&#xff0c;其中第一部分计划时间一个月&#xff0c;主要跟着黑马视频教程&#xff0c;学习路线如下&#xff0c;不定时更新&#xff0c;欢迎关注。 当前章节处于&#xff1a; ---------第1阶段-C基础入门 ---------第2阶段实战…

[ctf.show 元旦水友赛 2024] crypto

感觉半个多月回家没有打开过电脑了。看到ctf.show上元旦的比赛&#xff0c;才想起似乎应该看看。 月月的爱情故事 上来这就是个小脑洞题&#xff0c;给了一大段文字和一个base64的串。并且提示&#xff1a;试试摩斯吧&#xff01; 从文字上看只有三种标点符号&#xff0c;显…