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

news2024/12/30 3:23:20

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

目录

一、项目结构

二、辅助代码a.h

三、红黑树代码rbtree.h

四、测试代码main.cpp

五、运行效果

六、代码详解


一、项目结构

        这里给出的代码是实际可以运行的代码。

        运行环境:VS2022,控制台项目,64位。注意,VS的数据类型和UNix/Linux是不一样的,64位下long仍然是32位的,long long才是64位。

        包含三个文件,一个辅助文件,主要是树形显示的代码,一个头文件,是红黑树代码,一个主文件,是测试代码,包含main函数。

二、辅助代码a.h

         树形显示的代码,没有这个很难调试。

#include <string>
#include <vector>
using namespace std;


struct _cell
{
	string value;
};
struct _record
{
	vector<_cell > cells;
};
class Table
{
private:
	vector<_record > m_bodys;

	size_t _GetColCount(vector<_record > const& trs)
	{
		vector<_record >::const_iterator it;
		size_t maxcount = 0;
		for (it = trs.begin(); it != trs.end(); ++it)
		{
			if (it->cells.size() > maxcount)maxcount = it->cells.size();
		}
		return maxcount;
	}
	size_t GetActualColCount()
	{
		//这个值是定义的列的数目和每个行的列数目之最大者
		size_t maxcount = 0;
		if (_GetColCount(m_bodys) > maxcount)maxcount = _GetColCount(m_bodys);
		return maxcount;
	}
public:
	//设置数据,行必须有效,但可随意跳过一些列
	void SetData(size_t lineindex, size_t colindex, string const& data)
	{
		if (lineindex >= m_bodys.size())m_bodys.resize(lineindex + 1);
		if (colindex >= m_bodys[lineindex].cells.size())m_bodys[lineindex].cells.resize(colindex + 1);
		m_bodys[lineindex].cells[colindex].value = data;
	}
	//计算输出长度
	size_t outputlen(string const& s)
	{
		return utf8outputlen(s.c_str());
	}
	//utf-8中文通常为3个字节,输出仍为两个字符宽度
	size_t utf8outputlen(char const* s)
	{
		char const* p = s;
		long count_ansi = 0;
		long count_other = 0;
		while (*p)
		{
			if (*p < 0)++count_other;
			else ++count_ansi;

			++p;
		}
		return count_ansi + count_other * 2 / 3;
	}
	//head_tail_n==0显示全部,否则只显示前后head_tail_n
	string MakeTextTable(size_t head_tail_n = 0)
	{
		string ret;
		size_t i, j;
		size_t actualcount = this->GetActualColCount();
		vector<size_t > v_colmaxlen;//列的最大宽度
		v_colmaxlen.reserve(actualcount);
		for (i = 0; i < actualcount; ++i)
		{
			v_colmaxlen.push_back(0);
			for (j = 0; j < m_bodys.size(); ++j)
			{
				if (i < m_bodys[j].cells.size())
				{
					string data = m_bodys[j].cells[i].value;
					if (outputlen(data) > v_colmaxlen[i])v_colmaxlen[i] = outputlen(data);
				}
			}
		}

		ret = "";
		string str;

		ret += "\n";
		for (i = 0; i < actualcount; ++i)
		{
			str.assign(v_colmaxlen[i], '-');
			ret += str;
			ret += " ";
		}
		ret += "\n";
		bool first_skip = true;
		for (j = 0; j < m_bodys.size(); ++j)
		{
			if (head_tail_n > 0 && j >= head_tail_n && j < m_bodys.size() - head_tail_n)
			{
				if (first_skip)
				{
					first_skip = false;
					ret += "......\n";
				}
				else continue;
			}
			else
			{
				for (i = 0; i < m_bodys[j].cells.size(); ++i)
				{
					string data = m_bodys[j].cells[i].value;
					str.assign(v_colmaxlen[i] - outputlen(data), ' ');
					ret += data;
					ret += str;

					ret += " ";
				}
				ret += "\n";
			}
		}
		for (i = 0; i < actualcount; ++i)
		{
			str.assign(v_colmaxlen[i], '-');
			ret += str;
			ret += " ";
		}
		ret += "\n";

		return ret;
	}
};

        这个类本来很大的,我删掉了所有不相关代码,只保留了显示树形结构的代码。这个代码在此文有介绍:程序设计:控制台输出二叉树 二叉树的形象显示-CSDN博客

        这个代码不算复杂,其中计算输出长的outputlen是有问题的,没有真正按照字符数计算,一般我们只用asccii字符,不用中文,一般不会有问题(除非混有\t\r\n之类的格式字符)。

三、红黑树代码rbtree.h

        这个代码是比较长的,后面会拆解分析主要代码。

#pragma once

#include "a.h"
#include <iomanip>

extern bool G_IS_DEBUG;
#define thelog cout<<setw(5)<<__LINE__<<" : "
#define debug_log if(G_IS_DEBUG)thelog
#define endi endl
#define ende " [ERROR]"<<endl

typedef long long T_SHM_SIZE;

#define ARRAY_CAPACITY 10000

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;

struct TREE_NODE
{
	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;

	TREE_NODE() :hParent(-1), hLeft(-1), hRight(-1), bColorRed(true), deleted(0) {}
	TREE_NODE(T_SHM_SIZE parent, T_DATA const& tmp) :hParent(parent), hLeft(-1), hRight(-1), bColorRed(true), deleted(0), data(tmp) {}
	string& toString(string& str, void* = NULL)const
	{
		char buf[2048];
		string tmp;
		if (-1 == _me())strcpy(buf, "空节点");
		else sprintf_s(buf, 2048, "%8lld : %8lld %8lld %8lld %s %1d : %10s", _me(), hParent, hLeft, hRight, (bColorRed ? "R" : "B"), deleted, data.toString(tmp).c_str());
		return str = buf;
	}
	string toString2(bool left,bool bStruct)const
	{
		if (-1 == _me())return "空节点";
		char buf[2048];
		string ret;
		if (!bStruct)
		{
			sprintf_s(buf, 2048, "%lld%s%lld", _me(), (bColorRed ? "+" : "-"), data.n);
			if (left)
			{
				ret = "[";
				ret += buf;
			}
			else
			{
				ret = buf;
				ret += "]";
			}
		}
		else
		{
			sprintf_s(buf, 2048, "p%lld L%lld R%lld", hParent, hLeft, hRight);
			ret = buf;
		}
		return ret;
	}
	bool operator < (TREE_NODE const& tmp)const
	{
		T_COMP comp;
		return comp(data, tmp.data);
	}

	static TREE_NODE& at(T_SHM_SIZE n);
	T_SHM_SIZE _me()const;
	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();
	}
	void _CopyWithoutData(TREE_NODE const& tmp)
	{
		hParent = tmp.hParent;
		hLeft = tmp.hLeft;
		hRight = tmp.hRight;
		bColorRed = tmp.bColorRed;
		deleted = tmp.deleted;
	}
};

class CRBTree
{
public:
	struct iterator
	{
		T_SHM_SIZE handle;

		iterator() :handle(-1) {}
		bool operator == (iterator const& tmp)const { return handle == tmp.handle; }
		bool operator != (iterator const& tmp)const { return !(*this == tmp); }
		T_DATA& operator * ()const
		{
			return TREE_NODE::at(handle).data;
		}
		T_DATA* operator -> ()const
		{
			return &(operator *());
		}
		iterator& operator ++ ()
		{
			if (-1 != TREE_NODE::at(handle).hRight)
			{//存在右子树,取右子树的begin
				handle = TREE_NODE::at(handle).hRight;
				handle = TREE_NODE::at(handle)._begin();
			}
			else if (-1 != TREE_NODE::at(handle).hParent)
			{//存在父节点
				if (TREE_NODE::at(handle).isRight())
				{//是父节点的右子树,向上找到是左子树的节点,取这个节点的父节点
					while ((handle = TREE_NODE::at(handle).hParent) != -1 && TREE_NODE::at(handle).isRight()) {}
					if (-1 != handle && !TREE_NODE::at(handle).isRight())handle = TREE_NODE::at(handle).hParent;
				}
				else
				{//是父节点的左子树,取父节点
					handle = TREE_NODE::at(handle).hParent;
				}
			}
			else
			{//根节点且没有右子树,结束
				handle = -1;
			}
			return *this;
		}
		iterator& operator -- ()
		{
			if (-1 != TREE_NODE::at(handle).hLeft)
			{//存在左子树,取左子树的end
				handle = TREE_NODE::at(handle).hLeft;
				handle = TREE_NODE::at(handle)._end();
			}
			else if (-1 != TREE_NODE::at(handle).hParent)
			{//存在父节点
				if (TREE_NODE::at(handle).isLeft())
				{//是父节点的左子树,向上找到是右子树的节点,取这个节点的父节点
					while ((handle = TREE_NODE::at(handle).hParent) != -1 && TREE_NODE::at(handle).isLeft()) {}
					if (-1 != handle && !TREE_NODE::at(handle).isLeft())handle = TREE_NODE::at(handle).hParent;
				}
				else
				{//是父节点的右子树,取父节点
					handle = TREE_NODE::at(handle).hParent;
				}
			}
			else
			{//根节点且没有右子树,结束
				handle = -1;
			}
			return *this;
		}
	};
	typedef iterator const_iterator;
	struct TREE_HEAD
	{
		T_SHM_SIZE hHead;
		T_SHM_SIZE size;
		T_SHM_SIZE free_head;//空闲地址头指针

		TREE_HEAD() :hHead(-1), size(0), free_head(-1) {}

		//用于输出数据的场合
		string& toString(string& str)const
		{
			char buf[2048];
			sprintf_s(buf, 2048, "head %lld size %lld", hHead, size);
			return str;
		}
	};

	struct T_SETARRAY
	{
		//新版数组头
		struct array_head
		{
			T_SHM_SIZE capacity;
			T_SHM_SIZE size;
		};
		array_head _array_head;
		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;
			}
		}

	};
private:
	TREE_HEAD _tree_head;
private:
	//insert时如果已经存在保存被覆盖的数据
	bool m_OldValueSeted;
	T_DATA m_OldValue;
public:
	T_SETARRAY m_array;//内置数组对象,存储实际数据
	TREE_HEAD* tree_head = &_tree_head;//指向树的头
	CRBTree() :m_OldValueSeted(false)
	{
		m_array._array_head.capacity = ARRAY_CAPACITY;
		m_array._array_head.size = 0;
	}
	T_SHM_SIZE size()const { return tree_head->size; }
	T_SHM_SIZE capacity()const { return m_array.GetHead()->capacity; }
	const_iterator begin()const
	{
		const_iterator it;
		if (-1 == tree_head->hHead)it.handle = -1;
		else it.handle = TREE_NODE::at(tree_head->hHead)._begin();
		return it;
	}
	const_iterator end()const
	{
		const_iterator it;
		it.handle = -1;
		return it;
	}

	bool _check_handle(T_SHM_SIZE h)const
	{
		return h >= -1 && h < m_array.GetHead()->size;
	}
	bool _check_is_data_node(T_SHM_SIZE h)const
	{
		return h >= 0 && h < m_array.GetHead()->size;
	}
	//获取节点总数,包括自身
	T_SHM_SIZE _check_get_count(T_SHM_SIZE h)
	{
		//thelog << h << endi;
		T_SHM_SIZE n = 0;
		if (_check_is_data_node(h))
		{
			++n;
			//thelog << h << " " << TREE_NODE::at(h).hLeft<<" "<< TREE_NODE::at(h).hRight << endi;
			n += _check_get_count(TREE_NODE::at(h).hLeft);
			n += _check_get_count(TREE_NODE::at(h).hRight);
		}
		else
		{
			//thelog << "NULL" << endi;
		}
		return n;
	}
	//树形显示,px为偏移量,左边元素数
	void _check_show_tree(Table& table, T_SHM_SIZE h, bool left = true, T_SHM_SIZE line = 0, T_SHM_SIZE px = 0)
	{
		//thelog << h << " " << line << " " << px << endi;
		if (!_check_is_data_node(h))
		{
			//thelog << "空" << endi;
			return;
		}

		T_SHM_SIZE leftCount = _check_get_count(TREE_NODE::at(h).hLeft);
		//thelog << "leftCount " << leftCount << endi;
		T_SHM_SIZE pos = px + leftCount;
		table.SetData(line * 2, pos, TREE_NODE::at(h).toString2(left, false));//设置自身数据
		table.SetData(line * 2 + 1, pos, TREE_NODE::at(h).toString2(left, true));//设置自身数据
		//thelog << "TREE_NODE::at(h).hLeft " << TREE_NODE::at(h).hLeft << endi;
		_check_show_tree(table, TREE_NODE::at(h).hLeft, true, line + 1, px);//处理左子项
		//thelog << "TREE_NODE::at(h).hRight " << TREE_NODE::at(h).hRight << endi;
		_check_show_tree(table, TREE_NODE::at(h).hRight, false, line + 1, pos + 1);//处理右子项
	}
	void debug()
	{
		if (G_IS_DEBUG)
		{
			Table table;
			_check_show_tree(table, tree_head->hHead);
			thelog << endl << table.MakeTextTable() << endi;
		}
	}

	//检查红黑树特征
	bool _check_rbtree()
	{
		if (-1 == tree_head->hHead)return true;
		if (TREE_NODE::at(tree_head->hHead).bColorRed)
		{
			thelog << "根节点不是黑色" << ende;
			return false;
		}
		T_SHM_SIZE count_black = -1;
		if (_check_rbtree_count(tree_head->hHead, count_black, 0, 0, false))
		{
			debug_log << "深度 " << count_black << endi;
			return true;
		}
		else
		{
			return false;
		}
	}
	bool _check_rbtree_count(T_SHM_SIZE h, T_SHM_SIZE& count_black, T_SHM_SIZE black, T_SHM_SIZE red, bool PisRed)
	{
		if (-1 == h)
		{
			if (-1 == count_black)
			{
				count_black = black;
				return true;
			}
			else
			{
				if (black != count_black || red > black)
				{
					thelog << "深度不正确 " << count_black << " " << black << " " << red << ende;
					return false;
				}
				return true;
			}
		}
		else
		{
			if (TREE_NODE::at(h).bColorRed)
			{
				if (PisRed)
				{
					thelog << "连续红节点 " << h << ende;
					return false;
				}
				return _check_rbtree_count(TREE_NODE::at(h).hLeft, count_black, black, red + 1,true)
					&& _check_rbtree_count(TREE_NODE::at(h).hRight, count_black, black, red + 1,true);
			}
			else
				return _check_rbtree_count(TREE_NODE::at(h).hLeft, count_black, black + 1, red,false)
				&& _check_rbtree_count(TREE_NODE::at(h).hRight, count_black, black + 1, red,false);
		}
	}

	//检查数据结构是否正确
	bool _check()const
	{
		debug_log << "检查树结构,如果检查过程中发生数据修改则检查可能会出错" << endi;

		{
			size_t count_data_array = 0;//数组中的有效数据个数
			T_SHM_SIZE h;
			for (h = 0; h < static_cast<T_SHM_SIZE>(m_array.size()); ++h)
			{
				if (!TREE_NODE::at(h).deleted)++count_data_array;
			}
			debug_log << "数组容量 " << m_array.capacity() << " 个数 " << m_array.size() << " 有效数据 " << count_data_array << endi;
			debug_log << "树结构容量 " << capacity() << " 个数 " << size() << endi;
			if (count_data_array != size())
			{
				thelog << "树结构大小与数组统计不符 " << size() << " " << count_data_array << ende;
				return false;
			}
		}

		T_SHM_SIZE max_handle = m_array.GetHead()->size - 1;//整个已分配空间的最大句柄
		size_t count_free = 0;//未用节点数(删除的)
		//获取自由节点数
		{
			if (!_check_handle(tree_head->free_head))
			{
				thelog << "free_head error " << tree_head->free_head << ende;
				return false;
			}
			T_SHM_SIZE h = tree_head->free_head;
			while (h >= 0)
			{
				if (!TREE_NODE::at(h).deleted)
				{
					thelog << "此节点未被标记为删除 " << h << ende;
					return false;
				}
				++count_free;
				if (TREE_NODE::at(h).hParent<-1 || TREE_NODE::at(h).hParent>max_handle)
				{
					thelog << "TREE_NODE::at(h).hParent error " << TREE_NODE::at(h).hParent << ende;
					return false;
				}
				h = TREE_NODE::at(h).hParent;
			}
		}
		if (count_free != m_array.size() - size())
		{
			thelog << "删除链表总数不正确 " << count_free << " " << m_array.size() - size() << ende;
			return false;
		}
		debug_log << "删除链表节点总数 " << count_free << endi;
		size_t count_used = 0;//已用节点数

		//获取已用节点数
		{
			T_COMP comp;
			iterator it = begin();
			iterator it_old = end();
			while (it != end())
			{
				if (!_check_handle(it.handle))
				{
					thelog << "无效的节点 " << it.handle << ende;
					return false;
				}
				if (TREE_NODE::at(it.handle).deleted)
				{
					thelog << "此节点被标记为删除 " << it.handle << ende;
					return false;
				}
				if (it_old == it)
				{
					thelog << "指针循环 [" << it_old.handle << "][" << it.handle << "]" << ende;
					return false;
				}
				if (it_old != end() && !comp(*it_old, *it))
				{
					string str1, str2;
					thelog << "节点数据比较错误 [" << it_old->toString(str1) << "][" << it->toString(str2) << "]" << ende;
					return false;
				}
				++count_used;
				it_old = it;
				++it;
			}
		}
		if (count_used != static_cast<size_t>(tree_head->size))
		{
			thelog << "begin->end != size " << count_used << " " << tree_head->size << ende;
			return false;
		}
		if (count_used != size())
		{
			thelog << "遍历获得节点数不正确 " << count_used << " " << size() << ende;
			return false;
		}

		debug_log << "检查完成,没有错误" << endi;
		return true;
	}
private:
	//替换数据(只在插入时使用)
	void _update(T_SHM_SIZE position, T_DATA const& tmp)
	{
		TREE_NODE::at(position).data = tmp;
	}

	//修改头指针指向 src 的改为指向des(除了旋转只在删除里用到)
	void _changeRoot(T_SHM_SIZE src, T_SHM_SIZE des)
	{
		TREE_NODE::at(des).hParent = TREE_NODE::at(src).hParent;
		if (TREE_NODE::at(des).hParent != -1)
		{
			//旋转后是左节点
			if (TREE_NODE::at(TREE_NODE::at(des).hParent).hLeft == src)
				TREE_NODE::at(TREE_NODE::at(des).hParent).hLeft = des;
			//旋转后是右节点
			else
				TREE_NODE::at(TREE_NODE::at(des).hParent).hRight = des;
		}
		else
		{
			tree_head->hHead = des;
		}
	}

	//右旋转
	void _RRotate(T_SHM_SIZE p)
	{
		debug_log << "右旋" << p << endi;
		//assert(p>=0&&p<tree_head->size);

		//DEBUG_LOG<<"当前位置"<<p <<"大小"<< tree_head->size <<endi;
		T_SHM_SIZE t_lchild = TREE_NODE::at(p).hLeft;
		TREE_NODE::at(p).hLeft = TREE_NODE::at(t_lchild).hRight;

		//右节点非空
		if (TREE_NODE::at(t_lchild).hRight != -1)
			TREE_NODE::at(TREE_NODE::at(t_lchild).hRight).hParent = p;

		//修改根节点父指针
		_changeRoot(p, t_lchild);

		TREE_NODE::at(p).hParent = t_lchild;
		TREE_NODE::at(t_lchild).hRight = p;

	}

	//左旋转
	void _LRotate(T_SHM_SIZE p)
	{
		debug_log << "左旋 " << p << endi;

		string tmp;
		debug_log << "p " << TREE_NODE::at(p).toString(tmp) << endi;

		T_SHM_SIZE t_rchild = TREE_NODE::at(p).hRight;
		debug_log << "t_rchild " << TREE_NODE::at(t_rchild).toString(tmp) << endi;

		TREE_NODE::at(p).hRight = TREE_NODE::at(t_rchild).hLeft;
		debug_log << "p " << TREE_NODE::at(p).toString(tmp) << endi;

		//右节点非空
		if (TREE_NODE::at(t_rchild).hLeft != -1)
		{
			TREE_NODE::at(TREE_NODE::at(t_rchild).hLeft).hParent = p;
			debug_log << "TREE_NODE::at(t_rchild).hLeft " << TREE_NODE::at(TREE_NODE::at(t_rchild).hLeft).toString(tmp) << endi;
		}

		//非根节点
		//DEBUG_LOG << "_LRotate t_rchild's parent" <<TREE_NODE::at(t_rchild).hParent <<endi;
		//修改根节点父指针
		_changeRoot(p, t_rchild);
		debug_log << "p " << TREE_NODE::at(p).toString(tmp) << endi;
		debug_log << "t_rchild " << TREE_NODE::at(t_rchild).toString(tmp) << endi;

		TREE_NODE::at(p).hParent = t_rchild;
		TREE_NODE::at(t_rchild).hLeft = p;
		debug_log << "p " << TREE_NODE::at(p).toString(tmp) << endi;
		debug_log << "t_rchild " << TREE_NODE::at(t_rchild).toString(tmp) << endi;
	}

	//交换颜色
	void _exchage_color(T_SHM_SIZE a, T_SHM_SIZE b)
	{
		bool tmp = TREE_NODE::at(a).bColorRed;
		TREE_NODE::at(a).bColorRed = TREE_NODE::at(b).bColorRed;
		TREE_NODE::at(b).bColorRed = tmp;
	}
	//是否是红色,-1当作黑色
	bool _isRed(T_SHM_SIZE h)
	{
		return h != -1 && TREE_NODE::at(h).bColorRed;
	}

	//插入的入口
	pair<iterator, bool> _insert(T_DATA const& tmp, T_COMP& comp)
	{

		pair<iterator, bool> tmppair;
		T_SHM_SIZE insert_position = -1;
		bool isLeft = true;//插入节点方向 默认左插入
		bool isInsert = false;
		if ((insert_position = __insert(tmp, tree_head->hHead, -1, isLeft, isInsert, comp)) >= 0)
		{
			tmppair.first.handle = insert_position;
			tmppair.second = isInsert;
			//DEBUG_LOG<<"插入节点"<<insert_position<<"数据 "<<show(insert_position) <<endi;
		}
		else
		{
			//插入失败或者空间已满
			thelog << "插入节点失败" << ende;
			tmppair.first.handle = -1;
			tmppair.second = false;
		}

		TREE_NODE::at(tree_head->hHead).bColorRed = false;//根节点始终是黑色,因为转置的时候不能改颜色,所以只能在最后改

		return tmppair;

	}
	//插入节点返回-1不成功,vp父节点的子节点(即试图在此处插入),_parent父节点,taller 判断插入数据后节点深度是否增加
	T_SHM_SIZE __insert(T_DATA const& tmp, T_SHM_SIZE vp, T_SHM_SIZE _parent, bool isLeft, bool& isInsert, T_COMP& comp)
	{
		T_SHM_SIZE insert_position = -1;
		if (vp == -1)
		{
			//此位置为空,在此处插入
			insert_position = tree_head->free_head;
			___insert_new(tmp, insert_position, _parent, isLeft, isInsert);
			//DEBUG_LOG<<"insert_position="<<insert_position<<endi;
		}
		else
		{
			//此位置有数据,根据比较结果处理
			if (comp(TREE_NODE::at(vp).data, tmp))
			{
				//大,走右边
				if ((insert_position = __insert(tmp, TREE_NODE::at(vp).hRight, vp, false, isInsert, comp)) == -1)
				{
					return -1;
				}
			}
			else if (comp(tmp, TREE_NODE::at(vp).data))
			{
				//小,走左边
				if ((insert_position = __insert(tmp, TREE_NODE::at(vp).hLeft, vp, true, isInsert, comp)) == -1)
				{
					return -1;
				}
			}
			else
			{
				//相等,更新数据
				//thelog<<"插入数据已经存在"<<endw;
				m_OldValue = TREE_NODE::at(vp).data;//保存被覆盖的值
				m_OldValueSeted = true;//设置被覆盖的对象有效
				_update(vp, tmp);
				return vp;
			}
		}
		return insert_position;
	}
	//插入新节点,position为新节点的位置,来自空闲列表,parent为父节点的位置
	void ___insert_new(T_DATA const& data, T_SHM_SIZE& position, T_SHM_SIZE parent, bool isLeft, bool& isInsert)
	{
		if (position < 0)
		{
			//没有空闲位置,需要动态扩展长度
			if (m_array.Capacity() > m_array.Size())
			{
				TREE_NODE tmp;
				typename T_SETARRAY::HANDLE h;
				if (!m_array.Add(tmp, h))
				{
					thelog << "扩展数组出错" << ende;
					isInsert = false;
					return;
				}
				else
				{
					//tree_head = m_array.GetUserHead();算法测试不用
					position = h.handle;
				}
			}
			else
			{
				thelog << "空间已满,请申请更大空间!!!!!!!!!!!!!!!!!!" << ende;
				isInsert = false;
				return;
			}
		}
		else
		{
			//thelog<<"exist position="<<position<<endi;
		}
		tree_head->free_head = TREE_NODE::at(position).hParent;//空闲队列用hParent指向下一个
		//char buf[256];
		//sprintf(buf,"%ld %p",position,&TREE_NODE::at(position));
		//thelog<<buf<<endi;
		new(&TREE_NODE::at(position)) TREE_NODE(parent, data);
		//DEBUG_LOG<<show(position)<<endi;
		TREE_NODE::at(position).deleted = 0;
		if (parent == -1)
		{
			//没有父节点,空树
			tree_head->hHead = position;
			TREE_NODE::at(position).bColorRed = false;//根节点为黑色
		}
		else
		{
			//修改父节点
			//DEBUG_LOG<<show(parent)<<endi;
			if (isLeft)
			{
				TREE_NODE::at(parent).hLeft = position;
				//DEBUG_LOG<<show(parent)<<endi;
			}
			else
			{
				TREE_NODE::at(parent).hRight = position;
				//DEBUG_LOG<<show(parent)<<endi;
			}
			//平衡处理
			_RB_insert_Balance(position);
		}
		isInsert = true;
		//DEBUG_LOG<<"新增节点"<<position<<"["<<show(position)<<"]"<<endi;
		++tree_head->size;
		if (tree_head->size % 200000 == 0)
		{
			thelog << "树结构新增数据" << tree_head->size << endi;
		}
	}
	void _RB_insert_Balance(T_SHM_SIZE x)
	{
		T_SHM_SIZE p = TREE_NODE::at(x).hParent;
		if (!_isRed(p))return;

		//连续红,需要调整
		bool isLeft = (x == TREE_NODE::at(p).hLeft);
		T_SHM_SIZE g = TREE_NODE::at(p).hParent;
		bool isL = (p == TREE_NODE::at(g).hLeft);
		T_SHM_SIZE u = (isL ? TREE_NODE::at(g).hRight : TREE_NODE::at(g).hLeft);

		if (_isRed(u))
		{
			//u为红只需要染色,然后递归
			TREE_NODE::at(p).bColorRed = false;
			TREE_NODE::at(u).bColorRed = false;
			TREE_NODE::at(g).bColorRed = true;
			_RB_insert_Balance(g);
		}
		else
		{
			if (isL)
			{
				if (isLeft)
				{//LL
					_RRotate(g);
					_exchage_color(p, g);
				}
				else
				{//LR
					_LRotate(p);
					_RRotate(g);
					_exchage_color(x, g);
				}
			}
			else
			{
				if (isLeft)
				{//RL
					_RRotate(p);
					_LRotate(g);
					_exchage_color(x, g);
				}
				else
				{//RR
					_LRotate(g);
					_exchage_color(p, g);
				}
			}
		}
	}

	//删除指定节点,将节点接入到空闲链表
	void __erase_node(T_SHM_SIZE position)
	{
		debug_log << "删除节点 " << position << endi;
		TREE_NODE::at(position).hParent = tree_head->free_head;
		tree_head->free_head = position;
		TREE_NODE::at(position).hLeft = -1;
		TREE_NODE::at(position).hRight = -1;
		TREE_NODE::at(position).deleted = 1;

		--tree_head->size;
	}
	//删除中间节点,将中间节点替换为左子树最大值(数据不动,改变树结构)
	bool __erase_change_middle(T_SHM_SIZE const position, bool& vLeft, bool& vRed, T_SHM_SIZE& u, bool& uRed, T_SHM_SIZE& p)
	{
		string tmp;
		T_SHM_SIZE new_position = TREE_NODE::at(position).hLeft;
		if (-1 != new_position)
		{
			while (-1 != TREE_NODE::at(new_position).hRight)
			{
				new_position = TREE_NODE::at(new_position).hRight;
			}
		}
		debug_log << "position " << position << " new_position " << new_position << endi;
		debug_log << "position " << position << TREE_NODE::at(position).toString(tmp) << endi;
		debug_log << "new_position " << new_position << TREE_NODE::at(new_position).toString(tmp) << endi;

		vLeft = false;
		vRed = TREE_NODE::at(new_position).bColorRed;
		p = TREE_NODE::at(new_position).hParent;
		debug_log << "p " << TREE_NODE::at(p).toString(tmp) << endi;
		if (p != position)
		{
			debug_log << "非直接对调 p " << TREE_NODE::at(p).toString(tmp) << ende;
			TREE_NODE t;
			t._CopyWithoutData(TREE_NODE::at(new_position));
			TREE_NODE::at(new_position)._CopyWithoutData(TREE_NODE::at(position));
			TREE_NODE::at(position)._CopyWithoutData(t);

			debug_log << "position " << TREE_NODE::at(position).toString(tmp) << endi;
			debug_log << "new_position " << TREE_NODE::at(new_position).toString(tmp) << endi;

			//注意,这里无法用isLeft来判断,因为父节点的hLeft和hRight是旧数据
			if (TREE_NODE::at(new_position).hParent != -1)
			{
				if (TREE_NODE::at(TREE_NODE::at(new_position).hParent).hLeft == position)TREE_NODE::at(TREE_NODE::at(new_position).hParent).hLeft = new_position;
				else TREE_NODE::at(TREE_NODE::at(new_position).hParent).hRight = new_position;
			}
			if (TREE_NODE::at(position).hParent != -1)
			{
				if (TREE_NODE::at(TREE_NODE::at(position).hParent).hLeft==new_position)TREE_NODE::at(TREE_NODE::at(position).hParent).hLeft = position;
				else TREE_NODE::at(TREE_NODE::at(position).hParent).hRight = position;
			}
			
			if (TREE_NODE::at(new_position).hLeft != -1)TREE_NODE::at(TREE_NODE::at(new_position).hLeft).hParent = new_position;
			if (TREE_NODE::at(position).hLeft != -1)TREE_NODE::at(TREE_NODE::at(position).hLeft).hParent = position;

			if (TREE_NODE::at(new_position).hRight != -1)TREE_NODE::at(TREE_NODE::at(new_position).hRight).hParent = new_position;
			if (TREE_NODE::at(position).hRight != -1)TREE_NODE::at(TREE_NODE::at(position).hRight).hParent = position;
		}
		else
		{
			debug_log << "直接对调 p " << TREE_NODE::at(p).toString(tmp) << endi;
			TREE_NODE t;
			t._CopyWithoutData(TREE_NODE::at(new_position));
			TREE_NODE::at(new_position)._CopyWithoutData(TREE_NODE::at(position));
			TREE_NODE::at(position)._CopyWithoutData(t);
			debug_log << "position " << TREE_NODE::at(position).toString(tmp) << endi;
			debug_log << "new_position " << TREE_NODE::at(new_position).toString(tmp) << endi;

			//注意,这里无法用isLeft来判断,因为父节点的hLeft和hRight是旧数据
			if (TREE_NODE::at(new_position).hParent != -1)
			{
				if (TREE_NODE::at(TREE_NODE::at(new_position).hParent).hLeft == position)TREE_NODE::at(TREE_NODE::at(new_position).hParent).hLeft = new_position;
				else TREE_NODE::at(TREE_NODE::at(new_position).hParent).hRight = new_position;
			}
			TREE_NODE::at(position).hParent = new_position;

			TREE_NODE::at(new_position).hLeft=position;
			if (TREE_NODE::at(position).hLeft != -1)TREE_NODE::at(TREE_NODE::at(position).hLeft).hParent = position;

			if (TREE_NODE::at(new_position).hRight != -1)TREE_NODE::at(TREE_NODE::at(new_position).hRight).hParent = new_position;
			if (TREE_NODE::at(position).hRight != -1)TREE_NODE::at(TREE_NODE::at(position).hRight).hParent = position;
		}
	
		//如果是根节点
		if (-1 == TREE_NODE::at(new_position).hParent)
		{
			TREE_NODE::at(new_position).bColorRed = false;
			tree_head->hHead = new_position;
		}
		debug_log << "position " << TREE_NODE::at(position).toString(tmp) << endi;
		debug_log << "new_position " << TREE_NODE::at(new_position).toString(tmp) << endi;
		debug();

		return true;
	}

	//删除时做平衡,u可能是空节点
	bool _RB_erase_Balance(T_SHM_SIZE p, T_SHM_SIZE u)
	{
		if (-1 == p)
		{
			debug_log << "已经到顶,结束" << endi;
			return true;
		}

		string tmp;
		debug_log << "p " << TREE_NODE::at(p).toString(tmp) << endi;
		if (u != -1)debug_log << "u " << TREE_NODE::at(u).toString(tmp) << endi;
		else debug_log << "u -1" << endi;

		bool isL = (u == TREE_NODE::at(p).hRight);//兄弟节点是否是左节点
		T_SHM_SIZE s = (isL ? TREE_NODE::at(p).hLeft : TREE_NODE::at(p).hRight);
		T_SHM_SIZE r = -1;//s的红色子节点
		bool is_rL;//s的红色子节点是否是左节点
		debug_log << "平衡:p " << p << " u " << u << " s " << s << " TREE_NODE::at(s).hRight " << TREE_NODE::at(s).hRight << endi;
		if (TREE_NODE::at(s).hRight != -1 && TREE_NODE::at(TREE_NODE::at(s).hRight).bColorRed)
		{
			r = TREE_NODE::at(s).hRight;
			is_rL = false;
		}
		else if (TREE_NODE::at(s).hLeft != -1 && TREE_NODE::at(TREE_NODE::at(s).hLeft).bColorRed)
		{
			r = TREE_NODE::at(s).hLeft;
			is_rL = true;
		}
		else
		{
			r = -1;
			is_rL = false;//无意义
		}

		debug_log << "p " << p << " u " << u << " s " << s << " r(-1表示双黑) " << r << endi;
		debug();
		if (-1 == r)
		{
			debug_log << "s子节点均为黑" << endi;
			if (TREE_NODE::at(p).bColorRed)
			{
				debug_log << "p为红,s必为黑 s改为红p改为黑 结束" << endi;//s子节点均为黑,p改为黑,所以s改为红是安全的,不会造成双红
				TREE_NODE::at(s).bColorRed = true;
				TREE_NODE::at(p).bColorRed = false;
				debug();
			}
			else
			{
				debug_log << "p为黑" << endi;
				if (!TREE_NODE::at(s).bColorRed)
				{
					debug_log << "s为黑 s改为红平衡下层并向上递归" << endi;//p的左右分支均少1,所以p成为新的双黑节点
					//置s为红,p为新的u,递归
					TREE_NODE::at(s).bColorRed = true;
					debug();
					return _RB_erase_Balance(TREE_NODE::at(p).hParent, p);
				}
				else
				{
					debug_log << "s为红 " << TREE_NODE::at(s).toString(tmp) << endi;
					debug_log << TREE_NODE::at(TREE_NODE::at(s).hParent).toString(tmp) << endi;
					if (TREE_NODE::at(s).isLeft())
					{
						debug_log << "s为左 " << s << endi;
						//右旋p
						_RRotate(p);
					}
					else
					{
						debug_log << "s为右" << endi;
						_LRotate(p);
					}
					//p和s变色
					TREE_NODE::at(s).bColorRed = false;
					TREE_NODE::at(p).bColorRed = true;
					debug();
					//此时深度情况不变,但p变成了红,重新对p和u做平衡处理
					return _RB_erase_Balance(p, u);
				}
			}
		}
		else
		{
			if (isL && is_rL)
			{
				debug_log << "LL" << ende;
				TREE_NODE::at(r).bColorRed = TREE_NODE::at(s).bColorRed;
				TREE_NODE::at(s).bColorRed = TREE_NODE::at(p).bColorRed;
				_RRotate(p);
				TREE_NODE::at(p).bColorRed = false;
			}
			else if (isL && !is_rL)
			{
				debug_log << "LR" << endi;

				debug();

				TREE_NODE::at(r).bColorRed = TREE_NODE::at(p).bColorRed;
				debug();
				_LRotate(s);
				debug();
				_RRotate(p);
				debug();
				TREE_NODE::at(p).bColorRed = false;

				debug();
			}
			else if (!isL && is_rL)
			{
				debug_log << "RL------------------------" << endi;
				debug();
				TREE_NODE::at(r).bColorRed = TREE_NODE::at(p).bColorRed;
				debug();
				_RRotate(s);
				debug();
				string tmp;
				debug_log << "p " << TREE_NODE::at(p).toString(tmp) << endi;
				debug_log << "s " << TREE_NODE::at(p).toString(tmp) << endi;
				_LRotate(p);
				debug();
				TREE_NODE::at(p).bColorRed = false;
				debug();
			}
			else if (!isL && !is_rL)
			{
				debug_log << "RR" << endi;
				TREE_NODE::at(r).bColorRed = TREE_NODE::at(s).bColorRed;
				TREE_NODE::at(s).bColorRed = TREE_NODE::at(p).bColorRed;
				_LRotate(p);
				TREE_NODE::at(p).bColorRed = false;
			}
			else
			{
				thelog << "非预期的状态" << ende;
				return false;
			}
		}

		return true;
	}

	//删除
	bool _erase(T_SHM_SIZE position)
	{
		string  report;
		//DEBUG_LOG<<"开始删除...."<<Report(report) <<endi;

		bool vLeft;//删除的节点是左子节点
		bool vRed;//删除的节点是红色
		T_SHM_SIZE p = TREE_NODE::at(position).hParent;//父节点
		T_SHM_SIZE u;//替换节点
		bool uRed;//替换节点是红色(-1为黑色)

		if (TREE_NODE::at(position).hLeft != -1 && TREE_NODE::at(position).hRight != -1)
		{
			debug_log << "左右都存在,替换为左子树最大值" << endi;
			if (!__erase_change_middle(position, vLeft, vRed, u, uRed, p))return false;
			debug();
			return _erase(position);
		}
		else if (-1 == TREE_NODE::at(position).hLeft && -1 == TREE_NODE::at(position).hRight)
		{
			vLeft = TREE_NODE::at(position).isLeft();
			vRed = TREE_NODE::at(position).bColorRed;
			u = -1;
			uRed = false;

			if (-1 == p)
			{
				debug_log << "最后一个节点" << endi;
				tree_head->hHead = -1;
				vRed = true;//阻止后面继续处理,删除红色无需额外处理
			}
			else
			{
				debug_log << "叶子节点" << endi;
				if (TREE_NODE::at(position).isLeft())TREE_NODE::at(p).hLeft = -1;
				else TREE_NODE::at(p).hRight = -1;
			}
		}
		else
		{
			vLeft = TREE_NODE::at(position).isLeft();
			vRed = TREE_NODE::at(position).bColorRed;
			if (-1 != TREE_NODE::at(position).hLeft)
			{
				debug_log << "左子树存在" << endi;
				u = TREE_NODE::at(position).hLeft;
			}
			else
			{
				debug_log << "右子树存在" << endi;
				u = TREE_NODE::at(position).hRight;
			}
			if (-1 == p)
			{
				debug_log << "根节点" << endi;
				tree_head->hHead = u;
			}
			else
			{
				if (vLeft)TREE_NODE::at(p).hLeft = u;
				else TREE_NODE::at(p).hRight = u;
			}
			TREE_NODE::at(u).hParent = p;
			uRed = TREE_NODE::at(u).bColorRed;
			p = TREE_NODE::at(u).hParent;
		}

		bool ret = true;
		if (vRed)
		{
			debug_log << "删除红色节点,不用调整" << endi;
			//string tmp;
			//debug_log << "position " << TREE_NODE::at(position).toString(tmp) << endi;
			//debug_log << "p " << TREE_NODE::at(p).toString(tmp) << endi;
			//debug_log << "u " << TREE_NODE::at(u).toString(tmp) << endi;
			//TREE_NODE::at(u).hParent = p;
			//if (vLeft)TREE_NODE::at(p).hLeft = u;
			//else TREE_NODE::at(p).hRight = u;
			//debug_log << "position " << TREE_NODE::at(position).toString(tmp) << endi;
			//debug_log << "p " << TREE_NODE::at(p).toString(tmp) << endi;
			//debug_log << "u " << TREE_NODE::at(u).toString(tmp) << endi;
		}
		else if (!vRed && uRed)
		{
			debug_log << "删除黑色节点,替换节点红色改为黑色" << endi;
			TREE_NODE::at(u).bColorRed = false;
		}
		else
		{
			debug_log << "删除双黑节点================================================" << endi;
			ret = _RB_erase_Balance(p, u);
		}

		debug();
		if (ret)__erase_node(position);

		if (-1 != tree_head->hHead)TREE_NODE::at(tree_head->hHead).bColorRed = false;

		return ret;
	}
	string show(T_SHM_SIZE position)
	{
		char buf[2048];
		string tmp;
		TREE_NODE::at(position).toString(tmp);
		sprintf_s(buf, 2048, "%lld : %s", position, tmp.c_str());
		return buf;
	}
public:
	//如果second为false则已经存在,发生了覆盖,用GetOldValue获得被覆盖的值
	pair<iterator, bool> insert(T_DATA const& data)
	{
		T_COMP comp;
		return insert(data, comp);
	}
	pair<iterator, bool> insert(T_DATA const& data, T_COMP& comp)
	{
		m_OldValueSeted = false;//清除被覆盖对象的有效标志

		pair<iterator, bool> ret;

		ret.first = end();
		ret.second = false;
		if (tree_head->free_head < 0 && m_array.Capacity() <= m_array.Size())
		{
			thelog << "超出容量限制" << ende;
			return ret;
		}

		try
		{
			ret = _insert(data, comp);
		}
		catch (exception& e)
		{
			thelog << e.what() << ende;
		}
		//thelog<<"insert ret "<<ret.first.handle<<" "<<ret.second<<endi;
		return ret;
	}
	//返回被覆盖的值,如果最近的操作没有发生覆盖则false
	bool GetOldValue(T_DATA& ret)const
	{
		if (m_OldValueSeted)
		{
			ret = m_OldValue;
			return true;
		}
		else
		{
			return false;
		}
	}
	template<typename T_FIND >
	const_iterator find(T_FIND const& tmp)const
	{
		T_COMP comp;
		const_iterator it = lower_bound<T_FIND >(tmp);
		if (it != end())
		{
			if (comp(*it, tmp) || comp(tmp, *it))return end();
		}
		return it;
	}
	const_iterator find(T_DATA const& tmp, T_COMP& comp)const
	{
		const_iterator it = lower_bound(tmp, comp);
		if (it != end())
		{
			if (comp(*it, tmp) || comp(tmp, *it))return end();
		}
		return it;
	}
	bool erase(const_iterator it)
	{
		T_COMP comp;
		return erase(it, comp);
	}
	//删除并指向下一个
	iterator& DeleteAndMoveNext(iterator& it)
	{
		if (end() == it)return it;

		iterator& ret = it;
		iterator tmp = ret;
		++ret;
		erase(tmp);
		return ret;
	}
	bool erase(const_iterator it, T_COMP& comp)
	{
		if (it.handle < 0)return true;
		//DEBUG_LOG<<"要删除节点"<<show(it.handle)<<endi;
		bool ret = _erase(it.handle);
		//if(!_check())
		//{
		//	G_SET_ERROR(ZB_ERR_ERROR);
		//	Report();
		//}
		return ret;
	}
	bool erase(T_DATA const& data)
	{
		T_COMP comp;
		return erase(data, comp);
	}
	bool erase(T_DATA const& data, T_COMP& comp)
	{
		const_iterator it = find(data, comp);
		if (it.handle < 0)return true;
		return erase(it, comp);
	}
	//用全比较函数,实际是find的功能
	template<typename T_FIND >
	const_iterator lower_bound(T_FIND const& tmp)const
	{
		T_COMP comp;
		const_iterator it;

		T_SHM_SIZE hNode = tree_head->hHead;
		it.handle = -1;
		while (-1 != hNode)
		{
			if (comp(tmp, TREE_NODE::at(hNode).data))
			{
				it.handle = hNode;
				hNode = TREE_NODE::at(hNode).hLeft;
			}
			else if (comp(TREE_NODE::at(hNode).data, tmp))
			{
				hNode = TREE_NODE::at(hNode).hRight;
			}
			else
			{
				it.handle = hNode;
				break;
			}
		}

		return it;
	}
	//用部分比较函数(但必须是符合顺序的,否则结果不可预期)
	template<typename T_FIND, typename T_LESS_BOUND >
	const_iterator lower_bound(T_FIND const& tmp, T_LESS_BOUND comp)const
	{
		const_iterator it;

		T_SHM_SIZE hNode = tree_head->hHead;
		it.handle = -1;
		while (-1 != hNode)
		{
			if (comp(tmp, TREE_NODE::at(hNode).data))
			{
				it.handle = hNode;
				hNode = TREE_NODE::at(hNode).hLeft;
			}
			else if (comp(TREE_NODE::at(hNode).data, tmp))
			{
				hNode = TREE_NODE::at(hNode).hRight;
			}
			else
			{
				it.handle = hNode;
				hNode = TREE_NODE::at(hNode).hLeft;
			}
		}

		return it;
	}
	//用部分比较函数(但必须是符合顺序的,否则结果不可预期)
	template<typename T_FIND, typename T_LESS_BOUND >
	const_iterator upper_bound(T_FIND const& tmp, T_LESS_BOUND comp)const
	{
		const_iterator it;

		T_SHM_SIZE hNode = tree_head->hHead;
		it.handle = -1;
		while (-1 != hNode)
		{
			if (comp(tmp, TREE_NODE::at(hNode).data))
			{
				it.handle = hNode;
				hNode = TREE_NODE::at(hNode).hLeft;
			}
			else if (comp(TREE_NODE::at(hNode).data, tmp))
			{
				hNode = TREE_NODE::at(hNode).hRight;
			}
			else
			{
				hNode = TREE_NODE::at(hNode).hRight;
			}
		}

		return it;
	}
	//检查一个节点是否已经删除,必须是有效参数
	bool IsDeleted(T_SHM_SIZE handle)const
	{
		if (handle < 0 || handle >= m_array.capacity())return false;
		return TREE_NODE::at(handle).deleted;
	}
};

四、测试代码main.cpp

#include <iostream>
#include <vector>

#include "rbtree.h"

bool G_IS_DEBUG;

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;
}

//日志用格式
string TimeToString_log(time_t const & t1)
{
    if (0 == t1)return "";

    tm const * t2;
    char buf[256];
    t2 = localtime(&t1);
    sprintf(buf, "%02d-%02d %02d:%02d:%02d", t2->tm_mon + 1, t2->tm_mday, t2->tm_hour, t2->tm_min, t2->tm_sec);
    return buf;
}

bool test(int _seed, int count)
{
	CRBTree rbtree;
	T_DATA a;

	srand(_seed);
	vector<T_SHM_SIZE > datas;
	for (T_SHM_SIZE i = 0; i < count; ++i)
	{
		datas.push_back(rand());
	}

	debug_log << rbtree.size() << " " << rbtree.capacity() << endi;
	for (T_SHM_SIZE v : datas)
	{
		a.n = v;
		debug_log << a.n << endi;
		rbtree.insert(a);
	}
	debug_log << rbtree.size() << " " << rbtree.capacity() << endi;

	rbtree._check();
	rbtree._check_rbtree();
	//  CRBTree::const_iterator it = rbtree.begin();
	//  for (; it != rbtree.end(); ++it)
	//  {
	//      string tmp1,tmp2;
		  //thelog <<"h "<< it.handle << " 值:" << it->toString(tmp1) << " TREE_NODE:" << TREE_NODE::at(it.handle).toString(tmp2) << endi;
	//  }
	Table table;
	rbtree._check_show_tree(table, rbtree.tree_head->hHead);
	debug_log << endl << table.MakeTextTable() << endi;

	bool ret = true;
	for (T_SHM_SIZE v : datas)
	{
		a.n = v;
		debug_log << a.n << endi;
		ret = rbtree.erase(a) && rbtree._check() && rbtree._check_rbtree();
		if (G_IS_DEBUG)
		{
			Table table;
			rbtree._check_show_tree(table, rbtree.tree_head->hHead);
			thelog << endl << table.MakeTextTable() << endi;
		}
		if (!ret)break;
	}
	//CRBTree::const_iterator it = rbtree.begin();
	//for (; it != rbtree.end(); ++it)
	//{
	//	string tmp1, tmp2;
	//	thelog << "h " << it.handle << " 值:" << it->toString(tmp1) << " TREE_NODE:" << TREE_NODE::at(it.handle).toString(tmp2) << endi;
	//}
	return ret;
}
int main()
{
	G_IS_DEBUG = true;//大数据量测试时先设置为false,然后把后面循环的次数调大

	int count = 10;//每次测试的数据量,上限为 ARRAY_CAPACITY;
	for (int i = 0; i < 1; ++i)
	{
		if (!test(i, count))
		{
			G_IS_DEBUG = true;
			thelog << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" << endi;
			test(i, count);
			thelog << "失败 i= " << i << endi;
			return 1;
		}
		thelog << TimeToString_log(time(NULL)) << " " << i << endi;
		//break;
	}
	return 0;
}

五、运行效果

        以上三个代码就是全部代码,建立新工程,保存辅助代码和红黑树代码,用测试代码替换主代码,然后编译运行应该是没问题的。

        运行效果:

        由于是打开调试执行的,有很多输出,每一次改变树结构都有树形显示。

        最后结果:

        注意删除最后一个节点时调试输出为“删除红色节点,不用调整”,但是根节点其实是黑色的。这是因为代码里的临时变量把最后一个节点指示为红色,防止后面执行调整代码。这里算是个小缺陷吧(本该使用一个独立变量来指示的)。

六、代码详解

        算法实战:亲自写红黑树之三 算法详解-CSDN博客

(这里是结束)

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

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

相关文章

Python 如何实现适配器设计模式?什么是适配器(Adapter)设计模式?

什么是适配器设计模式&#xff1f; 适配器&#xff08;Adapter&#xff09;设计模式是一种结构型设计模式&#xff0c;它允许接口不兼容的类之间进行合作。适配器模式充当两个不兼容接口之间的桥梁&#xff0c;使得它们可以一起工作&#xff0c;而无需修改它们的源代码。 主要…

Hive入门--学习笔记

1&#xff0c;Apache Hive概述 定义&#xff1a; Hive是由Facebook开源用于解决海量结构化日志的数据统计&#xff0c;它是基于大数据生态圈Hadoop的一个数据仓库工具。 作用&#xff1a; Hive可以用于将结构化的数据文件【映射】为一张表&#xff0c;并提供类SQL查询功能。 H…

什么是原生IP与广播IP?如何区分?为什么需要用原生IP?

在代理IP中&#xff0c;我们常常听到原生IP与广播IP&#xff0c;二者有何区别&#xff1f;如何区分呢&#xff1f;下面为大家详细讲解。 一、什么是原生IP 原生IP地址是互联网服务提供商&#xff08;ISP&#xff09;直接分配给用户的真实IP地址&#xff0c;无需代理或转发。此…

OpenGL_Learn12(光照)

续OpenGL_Learn11&#xff08;光照&#xff09;-CSDN博客 1. 镜面高光 和漫反射光照一样&#xff0c;镜面光照也决定于光的方向向量和物体的法向量&#xff0c;但是它也决定于观察方向&#xff0c;例如玩家是从什么方向看向这个片段的。镜面光照决定于表面的反射特性。 我们通…

Redis:详解5大数据类型及其常用命令

目录 Redis键&#xff08;key&#xff09;字符串&#xff08;String&#xff09;简介常用命令数据结构简介常用命令 列表&#xff08;List&#xff09;简介常用命令数据结构 集合&#xff08;Set&#xff09;简介常用命令数据结构 哈希&#xff08;Hash&#xff09;简介常用命令…

Java排序算法之希尔排序

希尔排序&#xff08;Shell Sort&#xff09;又称“缩小增量排序”&#xff0c;是直接插入排序算法的一种更高效的改进版本。它的基本思想是&#xff1a;首先将整个数组按照一定的间隔分成若干个子序列&#xff0c;然后对每个子序列分别进行插入排序&#xff0c;减小间隔&#…

异步注解@Async失效的原因

在方法上加上Async注解&#xff0c;然后去启动类加上EnableAsync启动注解开启异步Async失效的原因 1、注解Async的方法不是public方法 2、注解Async的返回值只能为void或者Future 3、注解Async方法使用static修饰也会失效 4、spring无法扫描到异步类&#xff0c;没加注解Async …

AI大模型低成本快速定制法宝:RAG和向量数据库

文章目录 1. 前言2. RAG和向量数据库3. 论坛日程4. 购票方式 1. 前言 当今人工智能领域&#xff0c;最受关注的毋庸置疑是大模型。然而&#xff0c;高昂的训练成本、漫长的训练时间等都成为了制约大多数企业入局大模型的关键瓶颈。 这种背景下&#xff0c;向量数据库凭借其独特…

【yolov5报错解决】ModuleNotFoundError: No module named‘ultralytics.yolo‘

今天跑yolov5遇见一个报错&#xff0c;具体内容如下&#xff1a; 上面显示我没有ultralytics.yolo这个模块&#xff0c;但是我已经安装了ultralytics&#xff0c;同时&#xff0c;我也尝试了网上的方法pip install ultralytics.yolo&#xff0c;但是仍然得不到解决&#xff0c…

ai语音电销机器人电销行业要怎么降低封号率?

工信部对电话营销电话的管控越来越严格&#xff0c;企业电销行业的发展受到了很多限制&#xff0c;因为电话销售人员在进行销售工作的时候&#xff0c;经常会因为各种原因触发封号机制&#xff0c;导致手机卡号被封&#xff0c;那企业电销行业要怎么降低封号率&#xff1f; 很多…

图像格式导致halcon读取失败

图像格式&#xff1a; JPEG (jpg)&#xff0c;文件头&#xff1a;FF D8 FF PNG (png)&#xff0c;文件头&#xff1a;89 50 4E 47 GIF (gif)&#xff0c;文件头&#xff1a;47 49 46 38 Windows Bitmap (bmp)&#xff0c;文件头&#xff1a;42 4D 打开软件“notepad”使用16进…

win11无损关闭系统更新

1、窗口键R&#xff0c;打开运行窗口&#xff0c;输入regedit。 2、打开地址&#xff1a;计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings 3、新建DWORD&#xff08;32位&#xff09;值(D)&#xff0c;重命名“FlightSettingsMaxPauseDays” 4、…

正则匹配去除HTMl标签

正则匹配去除HTMl标签 案例&#xff1a;如在textarea中去除标签 操作方法 val.replace(/<[^>]>/g, ‘’))

基于SSM的校园停车场管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

Mysql执行报错:[Err] 1292 - Truncated incorrect DOUBLE value:***

MySQL执行语句抛出异常&#xff1a; 上面错误提示概是下面几种情况&#xff1a; 数据类型不匹配&#xff1a;在进行数值比较或运算时&#xff0c;数据类型可能不匹配。例如&#xff0c;将一个字符串值与一个 DOUBLE 类型的列进行比较或运算&#xff0c;或者将一个非数字字符串…

Qt QWebSocket实现JS调用C++

目录 前言1、QWebChannel如何与网页通信2、QWebSocketQWebChannel与网页通信2.1 WebSocketTransport2.2 WebSocketClientWrapper2.3 初始化WebSocket服务器2.4 前端网页代码修改 总结 前言 本篇主要介绍实现JS调用C的另一种方式&#xff0c;即QWebSocketQWebChannel。与之前的…

论文阅读:YOLOV: Making Still Image Object Detectors Great at Video Object Detection

发表时间&#xff1a;2023年3月5日 论文地址&#xff1a;https://arxiv.org/abs/2208.09686 项目地址&#xff1a;https://github.com/YuHengsss/YOLOV 视频物体检测&#xff08;VID&#xff09;具有挑战性&#xff0c;因为物体外观的高度变化以及一些帧的不同恶化。有利的信息…

韦东山linux驱动开发学习【常更】

1.linux目录简单介绍 2.直接运行需要在$path路径下

cmake简单使用

简介 理论上&#xff0c;任意一个C程序都可以用g来编译。 但当程序规模越来越大时&#xff0c;一个工程可能有许多个文件夹和源文件&#xff0c;这时输入的编译命令将越来越长。通常&#xff0c;一个小型C项目可能含有十几个类&#xff0c;各类间还存在着复杂的依赖关系。其中…

Unity优化(1)——合并Mesh

在某些移动端项目中&#xff0c;对于DrawCall的要求是很严格的&#xff0c;我们一般查看DrawCall可以通过Statistics里面的Batches进行查看&#xff0c;一般移动设备的Batches要控制在200左右比较合适&#xff0c;所以降低Batches是很重要的。 我们常常会遇到一个物体下挂载很多…