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

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

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

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


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

目录

一、几个不核心的类

二、树节点结构

三、树节点的HANDLE


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

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

一、几个不核心的类

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

cpp 复制代码
	//单字节标志组
	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;
		}
	};

遍历标志位的接口:

cpp 复制代码
	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~7
		bool GetUserFlag(int flag)const
		{
			return uflag->getflag(flag);
		}
		//设置一个节点的标志(即使节点已经删除,标志位仍然可能有用)flag 0~7
		bool SetUserFlag(int flag, bool value)const
		{
			return uflag->setflag(flag, value);
		}
	public:
		virtual bool doOneData(long handle, T_DATA const * pData) = 0;
	};

分多个子树的接口:

cpp 复制代码
	//set接口,用于分为N个子树的set
	template<typename T_DATA>
	class ISet
	{
	public:
		//IListSet遍历接口
		struct ISetForEach
		{
			long iSet;//非group对象为-1
			ISetForEach() :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;
		}
	};

二、树节点结构

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

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

cpp 复制代码
	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);
		}
	};

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

cpp 复制代码
	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

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

cpp 复制代码
	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();
		}
	};

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

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


(待续)

相关推荐
daiyang123...37 分钟前
测试岗位应该学什么
数据结构
kitesxian1 小时前
Leetcode448. 找到所有数组中消失的数字(HOT100)+Leetcode139. 单词拆分(HOT100)
数据结构·算法·leetcode
薯条不要番茄酱3 小时前
数据结构-8.Java. 七大排序算法(中篇)
java·开发语言·数据结构·后端·算法·排序算法·intellij-idea
盼海5 小时前
排序算法(五)--归并排序
数据结构·算法·排序算法
搬砖的小码农_Sky11 小时前
C语言:数组
c语言·数据结构
先鱼鲨生12 小时前
数据结构——栈、队列
数据结构
一念之坤12 小时前
零基础学Python之数据结构 -- 01篇
数据结构·python
IT 青年13 小时前
数据结构 (1)基本概念和术语
数据结构·算法
熬夜学编程的小王13 小时前
【初阶数据结构篇】双向链表的实现(赋源码)
数据结构·c++·链表·双向链表
liujjjiyun14 小时前
小R的随机播放顺序
数据结构·c++·算法