算法实战:亲自写红黑树之三 算法详解

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。


        此文承接:算法实战:亲自写红黑树之一-CSDN博客

                          算法实战:亲自写红黑树之二 完整代码-CSDN博客

目录

一、底层抽象

二、基本定义

三、TREE_NODE树节点结构

四、CRBTree容器结构

五、结构检查函数

六、插入的平衡算法

七、删除的平衡算法


一、底层抽象

        之前已经反复说过,我搞的东西都是在共享内存上运行的,不能使用指针,也就是相当于是在固定大小的数组上操作,实际实现考虑的东西还更多一些,所以对底层做了抽象。

        底层数据节点有一个索引位置,就是数组元素索引,有符号整数,定义为T_SHM_SIZE,-1代表无效。

        从索引到实际位置通过接口转换,具体实现为TREE_NODE的静态成员at(n),这是个关键点。测试代码使用的是静态数组,相关代码如下:

====================红黑树头文件:typedef long long T_SHM_SIZE;//静态数组大小
#define ARRAY_CAPACITY 10000====================测试代码文件://静态数组
TREE_NODE g_array[ARRAY_CAPACITY];//从索引到树节点
TREE_NODE& TREE_NODE::at(T_SHM_SIZE n)
{return g_array[n];
}//计算树节点自身的索引
T_SHM_SIZE TREE_NODE::_me()const
{return this - g_array;
}

二、基本定义

        本代码原来是模板代码,适用于各种不同的数据结构,所以沿用了几个类型定义:

        T_DATA 用户数据类型

        T_COMP 用户数据类型的比较方式,默认是less

        在这个测试代码里面将两个定义实现为:

struct CDemoData
{long long n = 0;//用于需要排序的场合bool operator < (CDemoData const& tmp)const { return n < tmp.n; }//某些场合也需要等于bool operator == (CDemoData const& tmp)const { return n == tmp.n; }friend ostream& operator << (ostream& o, CDemoData const& d){return o << d.n;}//用于输出数据的场合string& toString(string& str)const{char buf[2048];sprintf_s(buf, 2048, "%lld", n);return str = buf;}
};
typedef CDemoData T_DATA;
typedef less<T_DATA> T_COMP;

        由于相关代码实现的原因,用户数据类型必须按照CDemoData的样式写(也就是模板代码用到了这些功能),不支持简单类型。其实也不是没法支持简单类型,只不过因为实践中不可能在共享内存放简单类型,所以一开始没考虑,后来再修改需要改的地方就多了。

三、TREE_NODE树节点结构

        终于到了跟树有关的部分,树节点的结构和一般的树结点的结构相比多了删除标志deleted,因为数据是放在数组里面的,删除了位置还在,虽然说删除的节点位于删除链表,无法从树结构访问到,理论上并不需要额外的删除标志,但是为了检查数据结构有这个标志会好很多(由于共享内存的共享性,数据结构被破坏是比较频繁的)。另外由于对齐原因,多一个这个并不会增加树节点大小。

        树节点结构如下:

	T_SHM_SIZE hParent;//-1:无,根节点;0-N,子节点,或指向下个空闲地址T_SHM_SIZE hLeft;//-1表示无子节点T_SHM_SIZE hRight;//-1表示无子节点//颜色bool bColorRed;//是否为红色//删除标志signed char deleted;//0:有效,1:删除T_DATA data;

        树节点有一些内置方法,很容易理解。

四、CRBTree容器结构

        由于对底层做了抽象,容器内部包含一个数组对象T_SETARRAY,由这个对象提供底层数据,实际用到的就是添加(删除的属于树的删除链表,并不会归还给数组)。

        容器的另外一个数据成员就是TREE_HEAD指针,为什么是指针呢?因为共享内存是独立存在的,大部分操作是连接到已经存在的数据上去,所以是指针,包含的数组对象内部实际也同样是指针。

        在这个测试代码中直接内置了一个TREE_HEAD结构,以便与模板代码保持一致:

private:TREE_HEAD _tree_head;为了与共享内存操作一致,这个变量不可直接使用,只能使用tree_head
......
public:T_SETARRAY m_array;//内置数组对象,存储实际数据TREE_HEAD* tree_head = &_tree_head;//指向树的头

        TREE_HEAD结构:

	struct TREE_HEAD{T_SHM_SIZE hHead;T_SHM_SIZE size;T_SHM_SIZE free_head;//空闲地址头指针};

        底层数组T_SETARRAY结构:

	struct T_SETARRAY{//新版数组头struct array_head{T_SHM_SIZE capacity;T_SHM_SIZE size;};array_head _array_head;这个本来也是在共享内存的,所以不可直接使用,只能使用GetHead()array_head const* GetHead()const { return &_array_head; }T_SHM_SIZE capacity()const { return _array_head.capacity; }T_SHM_SIZE size()const { return _array_head.size; }T_SHM_SIZE Capacity()const { return _array_head.capacity; }T_SHM_SIZE Size()const { return _array_head.size; }struct HANDLE{T_SHM_SIZE handle;};bool Add(TREE_NODE const& data, HANDLE& h){if (_array_head.size == _array_head.capacity)return false;else{h.handle = _array_head.size;TREE_NODE::at(h.handle) = data;++_array_head.size;return true;}}};

        由于本代码底层用了静态数组,所以这个结构修改了内部实现,仅仅保持接口和原来相同。这个结构与算法基本没什么关系,不用太关注。

        容器还定义了迭代器iterator,符合一般的规则,代码也很简单。

        容器初始化很简单:

	CRBTree() :m_OldValueSeted(false){m_array._array_head.capacity = ARRAY_CAPACITY;m_array._array_head.size = 0;}

        初始化了数组的容量和大小。如果是共享内存,这些数据就要从共享内存获得。当然,这跟算法没什么关系。

五、结构检查函数

        有一组结构检查函数,用于检查数据是否正确。

  • bool _check_handle(T_SHM_SIZE h)const 检查h是否合法,必须大于等于-1,注意,不是检查是否是数据节点
  • bool _check_is_data_node(T_SHM_SIZE h)const 这才是检查是否是数据节点,不能是-1
  • T_SHM_SIZE _check_get_count(T_SHM_SIZE h) 获取节点总数,包括自身
  • void _check_show_tree(......) 显示树形结构
  • void debug() 无参数,显示整个树形结构
  • bool _check_rbtree() 检查红黑树特征,主要是调用下一个函数
  • bool _check_rbtree_count(......) 递归检测红黑树特征
  • bool _check()const 检查普通树特征,先调用这个检查树结构,再调用_check_rbtree检查红黑树特征

六、插入的平衡算法

        算法实战:亲自写红黑树之四 插入insert的平衡-CSDN博客

七、删除的平衡算法

        算法实战:亲自写红黑树之五 删除erase的平衡-CSDN博客


(这里是结束)

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

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

相关文章

动态规划:力扣LCR 188. 买卖芯片的最佳时机

题目 数组 prices 记录了某芯片近期的交易价格&#xff0c;其中 prices[i] 表示的 i 天该芯片的价格。你只能选择 某一天 买入芯片&#xff0c;并选择在 未来的某一个不同的日子 卖出该芯片。请设计一个算法计算并返回你从这笔交易中能获取的最大利润。 如果你不能获取任何利…

【软考高项】四十四、高级项目管理

一、项目集管理 相关角色 项目集发起人、项目集指导委员会、项目集经理、其他影响项目集的干系人项目集管理绩效域 项目集战略一致性、项目集效益管理、项目集干系人参与、项目集治理和项目集生命周期管理 二、项目组合管理 项目组合经理角色 项目组合管理原…

Imitation Learning学习记录(理论例程)

前言 最近还是衔接着之前的学习记录&#xff0c;这次打算开始学习模仿学习的相关原理&#xff0c;参考的开源资料为 TeaPearce/Counter-Strike_Behavioural_Cloning: IEEE CoG & NeurIPS workshop paper ‘Counter-Strike Deathmatch with Large-Scale Behavioural Clonin…

java项目之汽车资讯网站源码(springboot+mysql+vue)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的汽车资讯网站。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 汽车资讯网站的主要使用者管…

Vue从入门到实战Day04

一、组件的三大组成部分&#xff08;结构/样式/逻辑&#xff09; 1. scoped样式冲突 默认情况&#xff1a;写在组件中的样式会全局生效 -> 因此很容易造成多个组件之间的样式冲突问题。 1. 全局样式&#xff1a;默认组件中的样式会作用到全局 2. 局部样式&#xff1a;可以…

LeetCode 138. 随机链表的复制

目录 1.原题链接&#xff1a; 2.结点拆分&#xff1a; 代码实现&#xff1a; 3.提交结果&#xff1a; 4.读书分享&#xff1a; 1.原题链接&#xff1a; 138. 随机链表的复制 2.结点拆分&#xff1a; ①.拷贝各个结点&#xff0c;连接在原结点后面&#xff1b; ②.处…

【MySQL】基本操作

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;MySQL 目录 &#x1f449;&#x1f3fb;创建和删除数据库&#x1f449;&#x1f3fb;数据库编码集和数据库校验集校验规则对数据库的影响 &#x1f449;&…

【1 bit 翻转+无任何保护】MidnightsunQuals 2021 BroHammer

前言 又是一道非常有意思的题目&#xff0c;其实笔者很喜欢这种跟页表、特权级等相关的题目&#xff08;&#xff1a;虽然大多都无法独立做出来&#xff0c;但是通过这些题目可以学到很多的东西 题目分析 内核版本&#xff1a;v4.17.0smap/smep/kpti/kaslr 全关 题目给了源…

laravel8 导入 excel常见问题

上传xls 或 xlsx 文件后&#xff0c;文件解析为 zip 格式&#xff0c;输入正常情况&#xff0c;不影响解析 里面的内容 遇到解析内容&#xff0c;解析为空的情况&#xff0c;可能是 因为excel 存在多个 Sheet1 造成&#xff0c;服务器不能解析一个 Sheet1 的情况&#xff0…

智慧停车场管理系统主要组成

智慧泊车场办理体系&#xff0c;完成了泊车办理过程中的车辆类型分类、出场时的车牌辨认、行进路线的引导、空余车位诱导&#xff0c;以及准备离场前的反向寻车和方便缴费等全部环节。这六个流程中&#xff0c;泊车场对车辆的办理&#xff0c;进步了泊车场的运行效率&#xff0…

【网络】为什么TCP需要四次挥手?

在网络通信中&#xff0c;TCP&#xff08;传输控制协议&#xff09;是一种可靠的、面向连接的协议&#xff0c;它在数据传输过程中保证了数据的可靠性和顺序性。而TCP的连接建立过程只需要三次握手&#xff0c;但是TCP的挥手过程却需要四次挥手&#xff0c;这是为什么呢&#x…

数据分享—中国土壤有机质数据

土壤有机质数据是进行区域土地资源评价&#xff0c;开展自然地理研究常使用的数据&#xff0c;本期推文主要分享全国土壤有机质数据集。梧桐君会不定期分享地理信息数据&#xff0c;欢迎大家长期订阅。 数据来源 “万物土中生”&#xff0c;小编今天要分享的中国土壤有机质数…

Tomcat 内核详解 - Web服务器机制

详细介绍 Apache Tomcat 是一个开源的Web服务器和Servlet容器&#xff0c;它实现了Java Servlet、JavaServer Pages (JSP) 和WebSocket规范。Tomcat的核心设计围绕着几个关键组件&#xff0c;它们共同构成了处理HTTP请求、管理Web应用部署和执行Servlet逻辑的基础架构。 Apac…

牛客NC404 最接近的K个元素【中等 二分查找+双指针 Java/Go/PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/b4d7edc45759453e9bc8ab71f0888e0f 知识点 二分查找&#xff1b;找到第一个大于等于x的数的位置idx;然后从idx开始往两边扩展Java代码 import java.util.*;public class Solution {/*** 代码中的类名、方法名、…

小程序组件间传值

1、属性绑定&#xff08;Props&#xff09;: 父组件通过在子组件标签上设置属性的方式向子组件传值。 子组件通过properties定义接收的属性 父组件&#xff1a; wxml <child-component title"{{parentData}}"></child-component>子组件&#xff1a; js p…

可观测性监控

1 目的 常见的监控&#xff0c;主要是以收集数据以识别异常系统效应为主&#xff0c;多是单个服务&#xff0c;相互独立的状态。 可观测性&#xff0c;希望调查异常系统效应的根本原因&#xff0c;能够把多个服务、中间件、容器等串联起来&#xff0c;同时柔和metrics、log、…

前端怎么用 EventSource? EventSource怎么配置请求头及加参数? EventSourcePolyfill使用方法

EventSource EventSource 接口是 web 内容与服务器发送事件通信的接口。 一个 EventSource 实例会对 HTTP 服务器开启一个持久化的连接&#xff0c;以 text/event-stream 格式发送事件&#xff0c;此连接会一直保持开启直到通过调用 EventSource.close() 关闭。 EventSource…

常见的推荐系统框架

1&#xff09;Microsoft Recommender&#xff1a; 该框架由微软开发&#xff0c;可以免费使用&#xff0c;主要提供了包括一般功能&#xff08;Common Utilities&#xff09;、大数据功能&#xff08;Dataset Utilities&#xff09;、评价功能&#xff08;Evaluation Utilitie…

将本地docker镜像以压缩包格式保存至其他路径、从本地的镜像压缩包中加载docker镜像

保存本地Docker镜像为压缩包至其他路径 你可以使用 docker save 命令结合输出重定向&#xff08; -o 选项&#xff09;来将本地Docker镜像保存为一个压缩包&#xff08;通常是tar格式&#xff09;并直接保存到指定的路径。以下是一个示例命令&#xff1a; docker save -o /pa…

c++ - 在循环中使用迭代器删除 unordered_set 中的元素

标签 c unordered-set 请考虑以下代码: Class MyClass 为自定义类:class MyClass { public:MyClass(int v) : Val(v) {}int Val; };然后下面的代码将在调用 it T.erase(it); 之后在循环中导致 Debug Assertion Failed: unordered_set<MyClass*> T; unordered_set<…