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

        此文承接:算法实战:亲自写红黑树之一-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);
		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博客

(这里是结束)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

波束形成中的主瓣宽度

阵列信号处理相关基础知识及主瓣宽度 导向矢量阵列方向图确知波束形成普通波束形成主瓣宽度确知波束形成主瓣宽度普通波束形成主瓣宽度 在讨论主瓣宽度之前&#xff0c;首先得了解导向矢量、波束形成、阵列方向图的概念&#xff0c;这些是阵列信号处理中最基础的知识。 导向矢量…

编译智能合约以及前端交互工具库(Web3项目一实战之三)

我们已然在上一篇 Web3项目灵魂所在之智能合约编写(Web3项目一实战之二) ,为项目写好了智能合约代码。 但身为开发人员的我们,深知高级编程语言所编写出来的代码,都是需要经过编译,而后外部方能正常调用。很显然,使用solidity这门新的高级编程语言编写出来的智能合约,也…

【机器学习】线性回归算法:原理、公式推导、损失函数、似然函数、梯度下降

1. 概念简述 线性回归是通过一个或多个自变量与因变量之间进行建模的回归分析&#xff0c;其特点为一个或多个称为回归系数的模型参数的线性组合。如下图所示&#xff0c;样本点为历史数据&#xff0c;回归曲线要能最贴切的模拟样本点的趋势&#xff0c;将误差降到最小。 2. 线…

基于旗鱼算法优化概率神经网络PNN的分类预测 - 附代码

基于旗鱼算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于旗鱼算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于旗鱼优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络的光滑…

云表|低代码软件开发“外挂”,新时代的黑科技

随着技术的日新月异&#xff0c;现代企业对于软件开发的需求愈加迫切&#xff0c;传统的软件开发方式已然无法满足快速迭代和创新的需求。在这种背景下&#xff0c;低代码开发平台如破茧而出&#xff0c;应运而生。这种平台通过提供可视化的开发工具和预构建的组件&#xff0c;…

NVIDIA安装

电脑显卡类型 两种方法&#xff1a; 选择对应的版本 产品系列下载Notebooks&#xff0c;这样产品才会出现Laptop的GPU&#xff08;Laptop是代表笔记本&#xff09;。 下载完之后双击安装&#xff0c;更改下载路径后&#xff0c;选择默认的下载即可。 卸载 如果之后要卸载…

Spring6(三):面向切面AOP

文章目录 4. 面向切面&#xff1a;AOP4.1 场景模拟4.1.1 声明接口4.1.2 创建实现类4.1.3 创建带日志功能的实现类4.1.4 提出问题 4.2 代理模式4.2.1 概念4.2.2 静态代理4.2.3 动态代理4.2.4 测试 4.3 AOP概念4.3.1 相关术语①横切关注点②通知&#xff08;增强&#xff09;③切…

chrome 浏览器个别字体模糊不清

特别是在虚拟机里&#xff0c;有些字体看不清&#xff0c;但是有些就可以&#xff0c;设置办法&#xff1a; chrome://settings/fonts 这里明显可以看到有些字体就是模糊的状态&#xff1a; 把这种模糊的字体换掉即可解决一部分问题。 另外&#xff0c;经过观察&#xff0c;…

Neuro-Oncology | IF:15.9 CUTTag和RNA-seq联合解析胶质母细胞瘤的耐药性

发表单位&#xff1a;德克萨斯大学圣安东尼奥分校 发表日期&#xff1a;2023年1月18日 期 刊&#xff1a;Neuro-Oncology&#xff08;IF: 15.9&#xff09; 研究技术&#xff1a;CUT&Tag-seq、RNA-seq、RT-qPCR&#xff08;爱基百客均可提供&#xff09; 2023年1月1…

如何在10亿级别用户中检查用户名是否存在?

题目 不知道大家有没有留意过&#xff0c;在使用一些app注册的时候&#xff0c;提示你用户名已经被占用了&#xff0c;需要更换一个&#xff0c;这是如何实现的呢&#xff1f;你可能想这不是很简单吗&#xff0c;去数据库里查一下有没有不就行了吗&#xff0c;那么假如用户数量…

【人工智能实验】A*算法求解8数码问题 golang

人工智能经典问题八数码求解 实际上是将求解转为寻找最优节点的问题&#xff0c;算法流程如下&#xff1a; 求非0元素的逆序数的和&#xff0c;判断是否有解将开始状态放到节点集&#xff0c;并设置访问标识位为true从节点集中取出h(x)g(x)最小的节点判断取出的节点的状态是不…

Redis - 订阅发布替换 Etcd 解决方案

为了减轻项目的中间件臃肿&#xff0c;由于我们项目本身就应用了 Redis&#xff0c;正好 Redis 的也具备订阅发布监听的特性&#xff0c;正好应对 Etcd 的功能&#xff0c;所以本次给大家讲解如何使用 Redis 消息订阅发布来替代 Etcd 的解决方案。接下来&#xff0c;我们先看 R…

linux之shell

一、是什么 Shell是一个由c语言编写的应用程序&#xff0c;它是用户使用 Linux 的桥梁。Shell 既是一种命令语言&#xff0c;又是一种程序设计语言 它连接了用户和Linux内核&#xff0c;让用户能够更加高效、安全、低成本地使用 Linux 内核 其本身并不是内核的一部分&#x…

Java实现自定义windows右键菜单

要添加Java应用程序到Windows桌面的右键菜单&#xff0c;可以按照以下步骤操作&#xff1a; 创建一个新的.reg文件&#xff0c;并在文本编辑器中打开它。 添加以下代码到.reg文件中&#xff0c;将名称和路径替换为您的Java应用程序的名称和路径。 Windows Registry Editor V…

虚拟化热添加技术在数据备份上的应用

虚拟化中的热添加技术主要是指&#xff1a;无需停止或中断虚拟机的情况下&#xff0c;在线添加物理资源&#xff08;如硬盘、内存、CPU、网卡等&#xff09;的技术。热添加技术也是相比物理机一个非常巨大的优势&#xff0c;其使得资源分配变得更加灵活。 虚拟化中的热添加技术…

SOP作业指导书系统如何帮助厂家实现数字化转型

SOP&#xff08;Standard Operating Procedure&#xff0c;标准操作程序&#xff09;电子作业操作手册的应用对于厂家实现数字化转型起着至关重要的作用。本文将探讨SOP电子作业操作手册如何帮助厂家实现数字化转型的重要性和优势。 首先&#xff0c;SOP作业指导书可以提高生产…

idea菜单栏任务栏放缩比例修改

在编辑自定义VM选项中增加 -Dide.ui.scale0.8 参数 Help -> Edit Custom VM Options

这家提供数据闭环完整链路的企业,已拿下多家头部主机厂定点

“BEV感知数据闭环”已经成为新一代自动驾驶系统的核心架构。 进入2023年&#xff0c;小鹏、理想、阿维塔、智己、华为问界等汽车品牌正在全力推动从高速NOA到城区NOA的升级。在这一过程当中&#xff0c;如何利用高效的算力支撑、完善的算法模型、大量有效的数据形成闭环&…

Ubuntu部署OpenStack踩坑指南:还要看系统版本?

正文共&#xff1a;1515 字 12 图&#xff0c;预估阅读时间&#xff1a;2 分钟 到目前为止&#xff0c;我对OpenStack还不太了解&#xff0c;只知道OpenStack本身是一个云管理平台&#xff08;什么是OpenStack&#xff1f;&#xff09;。那作为云管理平台&#xff0c;我能想到最…