数组二叉树的基础操作

数组二叉树的实现

#include <iostream>
#include <cstdlib>
#include <cstdio>
// 默认的结点数量
#define MAXNODENUM (256)
// 代表不存在
#define NOTEXISTS  (-1)

// 判定引用计数所引用的对象是否依旧存在
#define EXISTS(o)  ((o) > 0 ? (true) : (false))

using namespace std;

class AryBitTree
{
#define DecRefCntPtr() ((m_nRefCntPtr && (*m_nRefCntPtr >= 1)) ? (--(*m_nRefCntPtr)) : NOTEXISTS)
#define IncRefCntPtr() (m_nRefCntPtr ? (++(*m_nRefCntPtr)) : NOTEXISTS)

#define LEFTCHILD(cur) ((cur) * (2) + (1))
#define RIGHTCHILD(cur) ((cur) * (2) + (2))

public:
	// 无参构造函数
	AryBitTree();
	// 含参构造函数
	AryBitTree(size_t nCapacity);
	// 拷贝构造函数
	AryBitTree(const AryBitTree &obj);
	// 移动构造函数
	AryBitTree(AryBitTree &&obj);
	// 析构函数
	~AryBitTree();
	// 赋值运算符重载
	AryBitTree &operator=(AryBitTree &obj);
	
	// 插入结点
	bool InsertNode(int iNum);
	// 删除结点
	bool DeleteNode(int iNum);
	// 创建二叉树
	bool CreateTree(const int *piArr, size_t nSize);
	// 前序遍历二叉树
	void PreOrderTraverse() const;
	// 中序遍历二叉树
	void InOrderTraverse() const;
	// 后序遍历二叉树
	void PostOrderTraverse() const;
	// 通过值找到下标索引
	int FindNode(int iNum) const;
private:
	// 前序遍历内部函数
	void PreOrderImpl(size_t nNodeIdx) const;
	// 后续遍历内部函数
	void PostOrderImpl(size_t nNodeIdx) const;
	// 中序遍历内部函数
	void InOrderImpl(size_t nNodeIdx) const;
private:
	// 初始化二叉树
	bool InitAryBitTree(size_t nCapacity = MAXNODENUM);
	// 释放二叉树
	void ReleaseBitTree();
private:
	int    *m_piTree;
	size_t  m_nSize;
	size_t  m_nCapacity;
	size_t *m_nRefCntPtr;
};

AryBitTree::AryBitTree() :
	m_piTree(nullptr), m_nSize(0), 
	m_nCapacity(MAXNODENUM), m_nRefCntPtr(nullptr)
{
	// 初始化数组二叉树
	InitAryBitTree();
}


AryBitTree::AryBitTree(size_t nCapacity) : 
	m_piTree(nullptr), m_nSize(0), 
	m_nCapacity(nCapacity), m_nRefCntPtr(nullptr)
{
	// 初始化数组二叉树
	InitAryBitTree(nCapacity);
}


AryBitTree::~AryBitTree()
{
	// 释放内存
	ReleaseBitTree();
}

AryBitTree::AryBitTree(const AryBitTree &obj)
{
	// 如果obj自身存在问题则默认初始化后直接返回
	if (!obj.m_piTree || !obj.m_nRefCntPtr)
	{
		InitAryBitTree();
		return;
	}
	// 执行浅拷贝
	m_nCapacity = obj.m_nCapacity;
	m_nSize = obj.m_nSize;
	m_piTree = obj.m_piTree;
	m_nRefCntPtr = obj.m_nRefCntPtr;
	// 增加引用计数
	IncRefCntPtr();
}

AryBitTree::AryBitTree(AryBitTree &&obj)
{
	// 执行移动操作
	m_nCapacity = obj.m_nCapacity;
	m_nSize = obj.m_nSize;
	m_piTree = obj.m_piTree;
	m_nRefCntPtr = obj.m_nRefCntPtr;

	obj.m_nCapacity = 0;
	obj.m_nSize = 0;
	obj.m_nRefCntPtr = nullptr;
	obj.m_piTree = nullptr;
}

AryBitTree & AryBitTree::operator=(AryBitTree &obj)
{
	// 如果obj自身存在问题则什么也不做直接返回
	if (!obj.m_piTree || !obj.m_nRefCntPtr)
	{
		return(*this);
	}
	// 降低自身引用计数, 或者直接自删除
	ReleaseBitTree();
	// 执行浅拷贝
	m_nCapacity = obj.m_nCapacity;
	m_nSize = obj.m_nSize;
	m_piTree = obj.m_piTree;
	m_nRefCntPtr = obj.m_nRefCntPtr;
	// 增加引用计数
	IncRefCntPtr();
}

bool AryBitTree::InsertNode(int iNum)
{
	bool    fOk		    = false;
	int    *pTmpArr	    = nullptr;
	size_t *pnTmpRefCnt = nullptr;
	size_t  nTmpCap     = 0;
	size_t  nTmpSize    = 0;

	do
	{
		// 容量满了, 需要扩容
		if (m_nSize >= m_nCapacity)
		{
			m_nCapacity = m_nCapacity + m_nCapacity / 2;
		}
		// 分配新的存储空间
		pTmpArr = new int[m_nCapacity];
		if (!pTmpArr)
		{
			break;
		}
		// 将原树内容拷贝到新缓冲区
		memcpy(pTmpArr, m_piTree, m_nSize * sizeof(m_piTree[0]));
		// 保存原来的大小
		nTmpSize = m_nSize;
		nTmpCap = m_nCapacity;
		// 降低原来的引用计数
		// 引用计数为0或者不存在则销毁
		ReleaseBitTree();

		// 重新存入大小
		m_nSize = nTmpSize;
		m_nCapacity = nTmpCap;
		// 插入结点
		pTmpArr[m_nSize++] = iNum;
		// 将剩余值置为INT_MAX代表未访问过
		for (size_t nIdx = m_nSize; nIdx < m_nCapacity; ++nIdx)
		{
			pTmpArr[nIdx] = INT_MAX;
		}
		// 新的引用计数
		pnTmpRefCnt = new size_t(1);
		if (!pnTmpRefCnt)
		{
			break;
		}
		// 指向新树和引用计数
		m_piTree = pTmpArr;
		m_nRefCntPtr = pnTmpRefCnt;

		fOk = true;
	} while (false);

	if (!fOk)
	{
		if (pnTmpRefCnt)
		{
			delete pnTmpRefCnt;
			pnTmpRefCnt = nullptr;
		}
		if (pTmpArr)
		{
			delete[] pTmpArr;
			pTmpArr = nullptr;
		}
	}

	return(fOk);
}

bool AryBitTree::DeleteNode(int iNum)
{
	bool fOk = false;
	int iPos = NOTEXISTS;
	int iLeftChild = 0;
	int iRightChild = 0;
	int iTmpRightChild = 0;
	int iTmpLeftChild = 0;
	int iLeftAndMostRight = 0;
	int *piTmpAry = nullptr;

	do
	{
		// 查找这个结点是否存在
		iPos = FindNode(iNum);
		if (NOTEXISTS == iPos)
		{
			break;
		}
		// 分配临时数组
		piTmpAry = new int[m_nSize];
		if (!piTmpAry)
		{
			break;
		}
		memcpy(piTmpAry, m_piTree, sizeof(piTmpAry[0]) * m_nSize);
		for (size_t nIdx = iPos; nIdx < m_nSize - 1; ++nIdx)
		{
				piTmpAry[nIdx] = m_piTree[nIdx + 1];
		}
		piTmpAry[m_nSize - 1] = INT_MAX;
		--m_nSize;

		fOk = CreateTree(piTmpAry, m_nSize);
	} while (false);

	return(fOk);
}

bool AryBitTree::CreateTree(const int *piArr, size_t nSize)
{
	bool fOk		= false;

	// 如果旧树存在, 并且新树的容量更大则进行扩容
	if (nSize >= m_nCapacity)
	{
		m_nCapacity = nSize + nSize / 2;
	}

	// 重新初始化树, 防止内部已经存在
	if (!InitAryBitTree(m_nCapacity))
	{
		return(false);
	}

	do
	{
		// 对树进行填充
		for (size_t nIdx = 0; nIdx < m_nCapacity; ++nIdx)
		{
			if (nIdx < nSize)
			{
				m_piTree[nIdx] = piArr[nIdx];
			}
			else
			{
				m_piTree[nIdx] = INT_MAX;
			}
		}
		m_nSize = nSize;

		fOk = true;
	} while (false);
	
	return(fOk);
}

void AryBitTree::PreOrderImpl(size_t nNodeIdx) const
{
	size_t nLeftChild = 0;
	size_t nRightChild = 0;

	if (nNodeIdx >= m_nSize)
	{
		return;
	}

	nLeftChild = LEFTCHILD(nNodeIdx);
	nRightChild = RIGHTCHILD(nNodeIdx);

	cout << m_piTree[nNodeIdx] << " ";
	PreOrderImpl(nLeftChild);
	PreOrderImpl(nRightChild);

	return;
}

void AryBitTree::PostOrderImpl(size_t nNodeIdx) const
{
	size_t nLeftChild = 0;
	size_t nRightChild = 0;

	if (nNodeIdx >= m_nSize)
	{
		return;
	}

	nLeftChild = LEFTCHILD(nNodeIdx);
	nRightChild = RIGHTCHILD(nNodeIdx);

	PreOrderImpl(nLeftChild);
	PreOrderImpl(nRightChild);
	cout << m_piTree[nNodeIdx] << " ";

	return;
}

void AryBitTree::InOrderImpl(size_t nNodeIdx) const
{
	size_t nLeftChild = 0;
	size_t nRightChild = 0;

	if (nNodeIdx >= m_nSize)
	{
		return;
	}

	nLeftChild = LEFTCHILD(nNodeIdx);
	nRightChild = RIGHTCHILD(nNodeIdx);

	PreOrderImpl(nLeftChild);
	cout << m_piTree[nNodeIdx] << " ";
	PreOrderImpl(nRightChild);
	
	return;
}

void AryBitTree::PreOrderTraverse() const
{
	if (!m_piTree || !m_nRefCntPtr || !m_nCapacity || !m_nSize)
	{
		return;
	}

	PreOrderImpl(0);
	cout << endl;

	return;
}

void AryBitTree::InOrderTraverse() const
{

	if (!m_piTree || !m_nRefCntPtr || !m_nCapacity || !m_nSize)
	{
		return;
	}

	InOrderImpl(0);
	cout << endl;

	return;
}

void AryBitTree::PostOrderTraverse() const
{

	if (!m_piTree || !m_nRefCntPtr || !m_nCapacity || !m_nSize)
	{
		return;
	}

	PostOrderImpl(0);
	cout << endl;

	return;
}

int AryBitTree::FindNode(int iNum) const
{
	for (size_t nIdx = 0; nIdx < m_nSize; ++nIdx)
	{
		if (m_piTree[nIdx] == iNum)
		{
			return(nIdx);
		}
	}

	return(NOTEXISTS);
}

bool AryBitTree::InitAryBitTree(size_t nCapacity /*= MAXNODENUM*/)
{
	bool	 fOk		= false;
	size_t	*pnRefCnt	= nullptr;
	int		*piTree		= nullptr;

	// 如果是0代表引用计数为0需要被销毁
	// 如果单纯引用计数为null可能其他内存未被销毁需要再次销毁
	// 后面需要继续初始化
	ReleaseBitTree();

	m_nSize = 0;
	m_nCapacity = nCapacity;

	do
	{
		// 重新分配空间
		piTree = new int[m_nCapacity];
		if (!piTree)
		{
			break;
		}
		// 重新分配引用计数, 当前引用为1
		pnRefCnt = new size_t(1);
		if (!pnRefCnt)
		{
			break;
		}
		// 填充树内每个值
		for (int i = 0; i < nCapacity; ++i)
		{
			piTree[i] = INT_MAX;
		}

		m_piTree = piTree;
		m_nRefCntPtr = pnRefCnt;

		fOk = true;
	} while (0);

	// 如果堆内存分配有问题则直接释放
	if (!fOk)
	{
		if (piTree)
		{
			delete[] piTree;
			piTree = nullptr;
		}
		if (pnRefCnt)
		{
			delete pnRefCnt;
			pnRefCnt = nullptr;
		}
	}
	
	return(fOk);
}

void AryBitTree::ReleaseBitTree()
{
	// 如果引用计数大于1则代表超过1个对象在引用, 这时
	// 直接降低引用计数后返回
	int iRet = 0;

	// 降低引用计数
	iRet = DecRefCntPtr();

	if (iRet != NOTEXISTS && iRet)
	{
		return;
	}
	// 释放
	if (m_piTree)
	{
		delete[] m_piTree;
		m_piTree = nullptr;
	}
	if (m_nRefCntPtr)
	{
		delete m_nRefCntPtr;
		m_nRefCntPtr = nullptr;
	}
	m_nCapacity = m_nSize = 0;
}

void TestFunc()
{
	AryBitTree bin;
	int iArr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

	bin.CreateTree(iArr, sizeof(iArr) / sizeof(iArr[0]));
	bin.PreOrderTraverse();
	bin.InOrderTraverse();
	bin.PostOrderTraverse();
	bin.InsertNode(11);
	bin.PreOrderTraverse();
	bin.InsertNode(15);
	bin.PreOrderTraverse();
	bin.DeleteNode(4);
	bin.PreOrderTraverse();
	bin.DeleteNode(1);
	bin.DeleteNode(2);
	bin.DeleteNode(5);
	bin.DeleteNode(11);
	bin.DeleteNode(15);
	bin.DeleteNode(3);
	bin.DeleteNode(6);
	bin.DeleteNode(7);
	bin.PreOrderTraverse();
	// 拷贝构造
	AryBitTree bin1 = bin;
	cout << "拷贝后的内容" << endl;
	bin1.PreOrderTraverse();

	AryBitTree bin2;
	bin2.CreateTree(iArr, 5);
	cout << "bin2原来的内容: ";
	bin2.PreOrderTraverse();
	bin2 = bin;
	cout << "bin2现在的内容: ";
	bin2.PreOrderTraverse();

	AryBitTree bin3 = static_cast<AryBitTree&&>(bin2);
}

int main()
{
	TestFunc();

	system("pause");
	return (0);
}

(完)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值