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

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

目录

一、项目结构

二、辅助代码a.h

三、红黑树代码rbtree.h

四、测试代码main.cpp

五、运行效果

六、代码详解


一、项目结构

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

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

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

二、辅助代码a.h

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

#include 
#include 
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 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 

extern bool G_IS_DEBUG;
#define thelog cout< 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(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(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&&psize);

		//DEBUG_LOG<<"当前位置"<

size < _insert(T_DATA const& tmp, T_COMP& comp) { pair 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<<"插入节点"<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="< 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="<free_head = TREE_NODE::at(position).hParent;//空闲队列用hParent指向下一个 //char buf[256]; //sprintf(buf,"%ld %p",position,&TREE_NODE::at(position)); //thelog<hHead = position; TREE_NODE::at(position).bColorRed = false;//根节点为黑色 } else { //修改父节点 //DEBUG_LOG<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<<"开始删除...."<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 insert(T_DATA const& data) { T_COMP comp; return insert(data, comp); } pair insert(T_DATA const& data, T_COMP& comp) { m_OldValueSeted = false;//清除被覆盖对象的有效标志 pair 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 "< const_iterator find(T_FIND const& tmp)const { T_COMP comp; const_iterator it = lower_bound(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<<"要删除节点"< 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 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 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 
#include 

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

五、运行效果

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

        运行效果:

算法实战:亲自写红黑树之二 完整代码_第1张图片

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

        最后结果:

算法实战:亲自写红黑树之二 完整代码_第2张图片

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

六、代码详解

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

(这里是结束)

你可能感兴趣的:(程序员造轮子(我的可重用代码),算法,红黑树)