11、实现基于共享内存的二叉树set

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

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

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


        实现数组肯定不是我们的目标,大部分情况下,我们用的是set和map(从set到map很简单,“set+数组”就可以实现map),核心问题是实现set。

目录

一、几个不核心的类

二、树节点结构

三、树节点的HANDLE


        大部分算法充斥了动态申请和释放,而STL的分配器比较难懂,也没研究出使用方法,因此无法直接使用STL的容器,所以要重新手写。(STL博大精深,我感觉是我还没学好)

        还有一个原因是一些早期编译器对STL的标准化支持不完善。

一、几个不核心的类

        单字节标志,用于记录删除、修改状态:

	//单字节标志组struct T_FLAG{unsigned char _flag;T_FLAG() :_flag(0) {}bool getflag(int flag)const{if (flag < 0 || flag >= 8){thelog << "无效的位 " << flag << ende;return false;}return _flag & (1 << flag);}bool setflag(int flag, bool value){if (flag < 0 || flag >= 8){thelog << "无效的位 " << flag << ende;return false;}_flag &= (0 << flag);//清位_flag |= ((value ? 1 : 0) << flag);return true;}};

        遍历标志位的接口:

	template<typename T_DATA>class IForEachFlag{protected:bool isDeleted;//是否是删除的,这个不是标志,表明数据是否已经删除T_FLAG * flag;//内置标志 位0 添加 位1修改(包括因为不存在而添加) 位2 删除T_FLAG * uflag;//用户标志public:void set(bool d, T_FLAG * f, T_FLAG * uf){isDeleted = d;flag = f;uflag = uf;}protected://检查一个节点的标志(即使节点已经删除,标志位仍然可能有用)bool GetFlagInsert()const{return flag->getflag(0);}bool GetFlagUpdate()const{return flag->getflag(1);}bool GetFlagDelete()const{return flag->getflag(2);}//设置一个节点的标志(即使节点已经删除,标志位仍然可能有用)bool ClearFlagInsert()const{return flag->setflag(0, false);}bool ClearFlagUpdate()const{return flag->setflag(1, false);}bool ClearFlagDelete()const{return flag->setflag(2, false);}bool SetFlagInsert()const{return flag->setflag(0, true);}bool SetFlagUpdate()const{return flag->setflag(1, true);}bool SetFlagDelete()const{return flag->setflag(2, true);}//检查一个节点的标志(即使节点已经删除,标志位仍然可能有用)flag 0~7bool GetUserFlag(int flag)const{return uflag->getflag(flag);}//设置一个节点的标志(即使节点已经删除,标志位仍然可能有用)flag 0~7bool SetUserFlag(int flag, bool value)const{return uflag->setflag(flag, value);}public:virtual bool doOneData(long handle, T_DATA const * pData) = 0;};

        分多个子树的接口:

	//set接口,用于分为N个子树的settemplate<typename T_DATA>class ISet{public://IListSet遍历接口struct ISetForEach{long iSet;//非group对象为-1ISetForEach() :iSet(-1) {}virtual bool doOneData(long handle, T_DATA const * pData) = 0;};public:virtual T_DATA * isetGet(long h)const{thelog << " ISet::isetGet 未实现" << ende;return NULL;}virtual long isetMoveNext(long & h)const{thelog << " ISet::isetMoveNext 未实现" << ende;return -1;}virtual long isetBegin()const{thelog << " ISet::isetBegin 未实现" << ende;return -1;}virtual pair<long, bool> isetInsert(T_DATA const & value){pair<long, bool> tmp;tmp.first = -1;tmp.second = false;thelog << " ISet::isetInsert 未实现" << ende;return tmp;}virtual long isetFind(T_DATA const & value)const{thelog << " ISet::isetFind 未实现" << ende;return -1;}virtual long isetFindLowerBound(T_DATA const & value, bool(*less)(T_DATA const &, T_DATA const &))const{thelog << " ISet::isetFindLowerBound 未实现" << ende;return -1;}virtual bool isetErase(long h){thelog << " ISet::isetErase 未实现" << ende;return -1;}virtual bool isetForEachShuffle(long handle, ISetForEach * pForEach)const{thelog << " IListSet::isetForEachShuffle 未实现" << ende;return true;}};

二、树节点结构

        树基于之前介绍的数组,树节点结构对应数组的模板参数。

        这是纯的结构,可供外部使用:

	template<typename T_DATA >struct T_TREE_NODE_STRUCT{T_SHM_SIZE hParent;//-1:无,根节点;0-N,子节点,或指向下个空闲地址T_SHM_SIZE hLeft;//-1表示无子节点T_SHM_SIZE hRight;//-1表示无子节点//平衡因子signed char bf;//balance_factor 0;平衡 1: 左子节点高 -1:右子节点高//删除标志signed char deleted;//0:有效,1:删除//额外标志T_FLAG flag;//内置标志 位0 添加 位1修改(包括因为不存在而添加) 位2 删除T_FLAG uflag;//用户标志//用户数据结构T_DATA data;T_TREE_NODE_STRUCT() :hParent(-1), hLeft(-1), hRight(-1), bf(EH), deleted(0) {}T_TREE_NODE_STRUCT(T_SHM_SIZE parent, T_DATA const & tmp) :hParent(parent), hLeft(-1), hRight(-1), bf(EH), deleted(0), data(tmp) {}string & toString(string & str, void * = NULL)const{char buf[2048];string tmp;sprintf(buf, "%8ld %8ld %8ld %1d %1d %3d %3d: %s", hParent, hLeft, hRight, bf, deleted, (unsigned int)flag._flag, (unsigned int)uflag._flag, data.toString(tmp).c_str());return str = buf;}static bool AddTableColumns(CHtmlDoc::CHtmlTable2 & table){table.AddCol("P", CHtmlDoc::CHtmlDoc_DATACLASS_RIGHT);table.AddCol("L", CHtmlDoc::CHtmlDoc_DATACLASS_RIGHT);table.AddCol("R", CHtmlDoc::CHtmlDoc_DATACLASS_RIGHT);table.AddCol("b", CHtmlDoc::CHtmlDoc_DATACLASS_RIGHT);table.AddCol("d", CHtmlDoc::CHtmlDoc_DATACLASS_RIGHT);table.AddCol("F", CHtmlDoc::CHtmlDoc_DATACLASS_RIGHT);table.AddCol("uF", CHtmlDoc::CHtmlDoc_DATACLASS_RIGHT);table.AddCol("|");return T_DATA::AddTableColumns(table);}bool AddTableData(CHtmlDoc::CHtmlTable2 & table)const{table.AddData(hParent);table.AddData(hLeft);table.AddData(hRight);table.AddData(bf);table.AddData(deleted);table.AddData((unsigned int)flag._flag);table.AddData((unsigned int)uflag._flag);table.AddData("|");return data.AddTableData(table);}};

        这是带有一些操作方法的结构,只能用在树模板内部:

	template<typename T_DATA, int PI_N, typename T_HANDLE, typename T_COMP >struct T_TREE_NODE : public T_TREE_NODE_STRUCT<T_DATA >{using T_TREE_NODE_STRUCT<T_DATA >::data;using T_TREE_NODE_STRUCT<T_DATA >::hLeft;using T_TREE_NODE_STRUCT<T_DATA >::hRight;using T_TREE_NODE_STRUCT<T_DATA >::hParent;T_TREE_NODE() {}T_TREE_NODE(T_SHM_SIZE parent, T_DATA const& tmp) :T_TREE_NODE_STRUCT<T_DATA >(parent, tmp) {}bool operator < (T_TREE_NODE const & tmp)const{T_COMP comp;return comp(data, tmp.data);}static T_TREE_NODE & at(T_SHM_SIZE n){if (n < 0){G_SET_ERROR(My_ERR_INVALID_HANDLE);thelog << "at error " << n << ende;}T_HANDLE array_handle(n);//char buf[256];//sprintf(buf,"%ld %p",n,&*array_handle);//theLog<<buf<<endi;return *(T_TREE_NODE *)(void *)&*array_handle;}T_SHM_SIZE _me()const{return T_HANDLE::_me(this);}T_SHM_SIZE _begin()const{if (-1 == hLeft)return _me();return at(hLeft)._begin();}T_SHM_SIZE _end()const{if (-1 == hRight)return _me();return at(hRight)._end();}bool isRight()const{return -1 != hParent && _me() == at(hParent).hRight;}bool isLeft()const{return !isRight();}};

三、树节点的HANDLE

        这个句柄当作指针时返回的是用户的数据(也就是不包含树结构本身):

	template<typename T_DATA, int PI_N >struct T_HANDLE_SET :public	T_HANDLE_ARRAY<T_TREE_NODE_STRUCT<T_DATA >, PI_N >{typedef T_TREE_NODE_STRUCT<T_DATA > T;typedef T_HANDLE_ARRAY<T, PI_N > T_PARENT;using T_PARENT::handle;T_HANDLE_SET(T_SHM_SIZE h = -1) :T_PARENT(h) {}T_HANDLE_SET(T_HANDLE_SET const& tmp) :T_PARENT(tmp.handle) {}using T_PARENT::iterator_category;using T_PARENT::pointer;using T_PARENT::element_type;using T_PARENT::value_type;using T_PARENT::difference_type;using T_PARENT::offset_type;using T_PARENT::reference;bool operator<(T_HANDLE_SET const& tmp)const { return handle < tmp.handle; }T_HANDLE_SET operator + (long n)const{T_HANDLE_SET tmp;tmp.handle = handle + n;return tmp;}T_HANDLE_SET operator - (long n)const{T_HANDLE_SET tmp;tmp.handle = handle - n;return tmp;}T_SHM_SIZE operator - (T_HANDLE_SET const& tmp)const { return handle - tmp.handle; }T_HANDLE_SET& operator += (T_SHM_SIZE n) { handle += n; return *this; }T_HANDLE_SET& operator ++ () { ++handle; return *this; }T_HANDLE_SET& operator -- () { --handle; return *this; }T_HANDLE_SET& operator = (T_HANDLE_SET const& tmp) { handle = tmp.handle; return *this; }bool operator == (T_HANDLE_SET const& tmp)const { return handle == tmp.handle; }bool operator != (T_HANDLE_SET const& tmp)const { return !((*this) == tmp); }T& operator * ()const{return *operator ->();}T* operator -> ()const{return T_PARENT::operator->();}static T_SHM_SIZE _me(T const* p, bool not_throw = false){return T_PARENT::_me(p, not_throw);}static void ShowVMapPrivateData(){return T_PARENT::ShowVMapPrivateData();}};

         这个树的设计不是很理想,但是因为其他数据结构都是基于这个的,所以也不容易改。(屎山开始了?)

        什么是理想的设计?自然而然就是最好的设计,不用刻意去理解


(待续)

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

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

相关文章

从数据库查询数据 写入Excel 写出JAVA代码

以下是一个示例代码,演示了如何从数据库中查询数据,然后将数据写入到Excel文件中: import java.io.FileOutputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import org.apache.poi.ss.user…

PostgreSQL创建表和自增序列

一、创建表&#xff1a; 注意&#xff1a; 1、在mysql没有序列的概念&#xff0c;id自增通过auto_increment实现&#xff1b; 2、pgsql没有auto_increment的概念&#xff0c;如何实现id自增&#xff1f;有两种方式&#xff1a; 方式一&#xff1a;创建序列&#xff0c;绑定…

面经学习(杭州实在智能实习)

个人评价 秃狼觉得本次的面试是有史以来难度最大的&#xff0c;问了很多陌生的八股文&#xff0c;项目问的比较少&#xff0c;估计是项目本来就没有什么亮点&#xff0c;也是第一次被面试官说菜的面试。不过在后续的学习上还是收获颇丰的。 1.说说你在实习中遇到的难点吧&…

K8S内存资源配置

在 Kubernetes (k8s) 中&#xff0c;资源请求和限制用于管理容器的 CPU 和内存资源。配置 CPU 和内存资源时&#xff0c;使用特定的单位来表示资源的数量。 CPU 资源配置 CPU 单位&#xff1a;Kubernetes 中的 CPU 资源以 “核” (cores) 为单位。1 CPU 核心等于 1 vCPU/Core…

SpringBoot RestHighLevelClient 按版本更新

SpringBoot RestHighLevelClient 按版本更新 1 查询2 更新 RestHighLevelClient 是 Elasticsearch 提供的一个用于与 Elasticsearch 集群交互的高级 REST 客户端。它是基于 Java 的客户端&#xff0c;旨在提供一种简单且功能丰富的方式来执行各种 Elasticsearch 操作&#xff0…

2024年海峡两岸创业青年研学交流项目火热开展中

7月17日&#xff0c;由浙江外国语学院国际商学院、创业学院主办的“文化之舟系两岸&#xff0c;潮头勇立浙商旗”——2024年海峡两岸大学生&#xff08;创业青年&#xff09;研学交流项目持续进行中。 上午&#xff0c;邵波副教授带领学生代表接待来自台湾的二十多名学生参加“…

利用 PHP 解锁 1688 详情 API 接口的秘密

在电商领域的探索中&#xff0c;1688 平台的商品详情数据无疑是一座宝藏。而通过 PHP 语言来解锁 1688 详情 API 接口的秘密&#xff0c;将为我们开启获取这一宝藏的大门。 一、深入了解 1688 详情 API 接口 1688 详情 API 接口提供了丰富的商品信息&#xff0c;包括商品描述、…

Linux输出重定向到文件立即输出

./md.out > output.txt 2>&1程序中断时&#xff0c;文件为空的原因可能是由于缓冲机制。标准输出&#xff08;stdout&#xff09;和标准错误输出&#xff08;stderr&#xff09;默认是缓冲的&#xff0c;这意味着数据在写入文件之前会先存储在缓冲区中。如果程序在缓…

【人工智能】在未来智慧城市的建设及应用分析

作者主页: 知孤云出岫 目录 作者主页:案例分析&#xff1a;人工智能在未来智慧城市的建设及其影响和应用引言一、人工智能在智慧城市中的关键应用领域 案例分析&#xff1a;人工智能在未来智慧城市的建设及其影响和应用 引言 智慧城市是利用信息和通信技术&#xff08;ICT&am…

电平的概念及应用(电路节点在某一时刻的电压状态)(高电平、低电平)(电压是推动电荷通过导体的力,而电平是这种力的表达形式)

文章目录 电平的概念及其在电子与电气应用中的应用1. 电平的基本概念1.1 电压与电平1.2 电流与电压的区分 2. 数字电路中的电平应用2.1 逻辑电平2.1.1 TTL电平2.1.2 CMOS电平 2.2 电平转换 3. 模拟电路中的电平应用3.1 信号表示3.2 信号放大 4. 电平在通信技术中的应用4.1 RS-4…

迁移学习在乳腺浸润性导管癌病理图像分类中的应用

1. 引言 乳腺癌主要有两种类型:原位癌:原位癌是非常早期的癌症&#xff0c;开始在乳管中扩散&#xff0c;但没有扩散到乳房组织的其他部分。这也称为导管原位癌(DCIS)。浸润性乳腺癌:浸润性乳腺癌已经扩散(侵入)到周围的乳腺组织。侵袭性癌症比原位癌更难治愈。将乳汁输送到乳…

Android Navigation 组件原理和使用教程

Android Navigation 组件是用于简化导航相关操作的框架&#xff0c;允许你在应用中管理应用内各个部分之间的导航。该组件是Android Jetpack的一部分&#xff0c;主要包含三个部分&#xff1a;导航图&#xff08;NavGraph&#xff09;、NavHost和NavController。 一、原理 Nav…

Kafka Producer之幂等性

文章目录 1. 启用幂等性2. 底层变化3. 数据不重复4. 数据有序 幂等性通过消耗时间和性能的方式&#xff0c;解决乱序和重复问题。 但是只能保证同一生产者在一个分区中的幂等性。 1. 启用幂等性 //创建producerHashMap<String, Object> config new HashMap<>();…

怎样在 PostgreSQL 中优化对大表的分区裁剪和索引选择?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 怎样在 PostgreSQL 中优化对大表的分区裁剪和索引选择一、分区裁剪&#xff1a;精准切割&#xff0c;提…

SQL Server 和 MySQL 的主要区别

架构 SQL Server 微软开发&#xff0c;闭源商业数据库运行在 Windows 和 Linux单一数据库引擎架构支持多个数据库实例和多种数据存储机制&#xff08;行存储和列存储&#xff09;包含数据库引擎、SQL Server Agent、SQL Server Reporting Services (SSRS)、SQL Server Integrat…

【自学安全防御】三、企业双机热备和带宽管理的综合实验

实验拓扑&#xff1a; 实验任务&#xff1a; 12&#xff0c;对现有网络进行改造升级&#xff0c;将当个防火墙组网改成双机热备的组网形式&#xff0c;做负载分担模式&#xff0c;游客区和DMZ区走FW3&#xff0c;生产区和办公区的流量走FW1 13&#xff0c;办公区上网用户限制流…

QML基本类型

QML基本数据类型之 int使用案例代码 <span style"color:#4b4b4b"><span style"background-color:#ffffff"><code class"language-JavaScript"><span style"color:#008000">// 定义 >> 整型&#xff08…

go-zero框架入门

go-zero框架环境的安装 goctl 若想用go-zero框架&#xff0c;还需要一些前置条件&#xff1a; 安装goctl go install github.com/zeromicro/go-zero/tools/goctllatest可以使用 goctl 命令查看是否安装成功 成功后安装protoc goctl env check --install --verbose --force…

如何免费用java c#实现手机在网状态查询

今天分享手机在网状态查询接口&#xff0c;该接口适用的场景非常广泛&#xff01;首先我们先讲下什么是手机在网状态&#xff1f;简单来说&#xff0c;就是你得手机号是否还在正常使用中&#xff0c;是否能够及时接收和回复信息&#xff0c;是否能够随时接听和拨打电话。如果你…

【Android】基础—基本布局

【Android】基础—基本布局 基本布局 线性布局 垂直方向&#xff1a; <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:orientation"vertical"…