《数据结构实战》创建一颗平衡二叉树

平衡二叉树是一种防止搜索二叉树退化成链表的树,平衡二叉树的左右子树的高度相差不超过1,因此在插入及删除时有必要重新旋转树,以达到是一颗平衡树。为简单起见,仅使用int型数据,并且在有相同节点时,更新nCount的值。代码如下:

#ifndef __CBALANCETREE__H
#define __CBALANCETREE__H

#include <iostream>

struct TreeNode
{
	int nData; // 节点的值
	TreeNode* lTree; // 左节点
	TreeNode* rTree; // 右节点
	int nHigh; // 树的高度
	int nCount; // 相同的值的次数
	TreeNode()
	{
		nData = 0;
		lTree = NULL;
		rTree = NULL;
		nHigh = 0;
		nCount = 0;
	}
};

inline int GetHigh(TreeNode* pNode) // 获取节点高度 空节点为-1
{
	if (pNode)
		return pNode->nHigh;
	return -1;
}

inline int Max(int a, int b)
{
	return a > b ? a : b;
}

class CBalanceTree // 平衡二叉树
{
public:
	CBalanceTree();
	~CBalanceTree();

public:
	bool InsertNode(int nValue); // 插入节点
	bool RemoveNode(int nValue); // 删除节点
	bool FindData(int nValue); // 查找是否有该节点
	void BreadthTraversal(); // 层序遍历
	void MiddleTraversal(); // 中序遍历 根左右
private:
	bool InsertNode(TreeNode*& pNode, int nValue);
	bool RemoveNode(TreeNode*& pNode, int nValue);
	bool FindNode(TreeNode* pNode, int nValue);
	void SignelRotateLeftLeft(TreeNode*& pNode); // 左左情况 单旋转
	void DoubleRotateLeftRight(TreeNode*& pNode); // 左右情况 双旋转
	void SignelRotateRightRight(TreeNode*& pNode); // 右右情况 单旋转
	void DoubleRotateRightLeft(TreeNode*& pNode); // 右左情况 双旋转
private:
	void MiddleTraversal(TreeNode* pNode);
	void DeleteNode(TreeNode*& pNode);
private:
	TreeNode* m_pRoot;
};


#endif

实现文件:

#include "BalanceTree.h"
#include <queue>

CBalanceTree::CBalanceTree()
{
	m_pRoot = NULL;
}


CBalanceTree::~CBalanceTree()
{
	DeleteNode(m_pRoot);
}

bool CBalanceTree::InsertNode(int nValue)
{
	return InsertNode(m_pRoot, nValue);
}

bool CBalanceTree::InsertNode(TreeNode*& pNode, int nValue)
{
	if (!pNode)
	{
		pNode = new TreeNode;
		pNode->nData = nValue;
		return true;
	}
	if (nValue < pNode->nData) // 左子树插入
	{
		InsertNode(pNode->lTree, nValue);
		if (2 == GetHigh(pNode->lTree) - GetHigh(pNode->rTree)) // 高度相差2 不平衡
		{
			if (GetHigh(pNode->lTree) > GetHigh(pNode->rTree)) // 左左情况 单旋转
				SignelRotateLeftLeft(pNode);
			else
				DoubleRotateLeftRight(pNode);  // 左右情况 双旋转
		}
	}
	else if (nValue > pNode->nData) // 右子树插入
	{
		InsertNode(pNode->rTree, nValue);
		if (2 == GetHigh(pNode->rTree) - GetHigh(pNode->lTree))
		{
			if (GetHigh(pNode->rTree) > GetHigh(pNode->lTree)) // 右右情况
				SignelRotateRightRight(pNode);
			else
				DoubleRotateRightLeft(pNode); // 右左情况
		}
	}
	else // 相同
		pNode->nCount += 1;
	// 更新树的高度
	pNode->nHigh = Max(GetHigh(pNode->lTree), GetHigh(pNode->rTree)) + 1;
	return true;
}

void CBalanceTree::SignelRotateLeftLeft(TreeNode*& pK1)
{
	TreeNode* pK2 = pK1->lTree;
	pK1->lTree = pK2->rTree;
	int nHigh = GetHigh(pK2->rTree);
	pK2->rTree = pK1;
	// 更新树的高度
	pK1->nHigh = Max(nHigh,GetHigh(pK1->rTree)) + 1;
	pK2->nHigh = Max(GetHigh(pK2->lTree), GetHigh(pK2->rTree)) + 1;
	pK1 = pK2;
}

void CBalanceTree::SignelRotateRightRight(TreeNode*& pK1)
{
	TreeNode* pK2 = pK1->rTree;
	int nHigh = GetHigh(pK2->lTree);
	pK1->rTree = pK2->lTree;
	pK2->lTree = pK1;

	// 更新树的高度
	pK1->nHigh = Max(nHigh, GetHigh(pK1->lTree)) + 1;
	pK2->nHigh = Max(GetHigh(pK2->lTree), GetHigh(pK2->rTree)) + 1;
	pK1 = pK2;
}

void CBalanceTree::DoubleRotateLeftRight(TreeNode*& pNode) // 左右情况
{
	SignelRotateRightRight(pNode->lTree); // 局部是右 
	SignelRotateLeftLeft(pNode);
}

void CBalanceTree::DoubleRotateRightLeft(TreeNode*& pNode) // 右左情况
{
	SignelRotateLeftLeft(pNode->rTree); // 局部是左
	SignelRotateRightRight(pNode);
}

bool CBalanceTree::RemoveNode(int nValue)
{
	return RemoveNode(m_pRoot, nValue);
}

bool CBalanceTree::RemoveNode(TreeNode*& pNode, int nValue)
{
	if (!pNode)
		return false; // 没有该节点
	if (pNode->nData == nValue)
	{
		if (pNode->nCount > 0)
		{
			pNode->nCount -= 1;
			return true;
		}
		else // 删除
		{
			if (pNode->lTree && pNode->rTree) // 有左右子树
			{
				// 找到右子树中最小的 即最左 替换该节点
				TreeNode* pTemp = pNode->rTree;
				while (pTemp->lTree)
					pTemp = pTemp->lTree;
				pNode->nCount = pTemp->nCount;
				pNode->nData = pTemp->nData;
				RemoveNode(pNode->rTree, pTemp->nData); // 删除该节点
				if (2 == GetHigh(pNode->lTree) - GetHigh(pNode->rTree))
				{
					if (GetHigh(pNode->lTree) > GetHigh(pNode->rTree)) // 左左情况
						SignelRotateLeftLeft(pNode);
					else
						DoubleRotateLeftRight(pNode);
				}
			}
			else // 仅有一个节点
			{
				if (pNode->rTree) // 有右节点
				{
					pNode->nData = pNode->rTree->nData;
					pNode->nCount = pNode->rTree->nCount;
					delete pNode->rTree;
					pNode->rTree = NULL;
				}
				else if (pNode->lTree) // 有左节点
				{
					pNode->nData = pNode->lTree->nData;
					pNode->nCount = pNode->lTree->nCount;
					delete pNode->lTree;
					pNode->lTree = NULL;
				}
				else
				{
					delete pNode;
					pNode = NULL;
					return true;
				}
			}
		}
	}
	else if (pNode->nData < nValue) // 右子树查找
	{
		RemoveNode(pNode->rTree, nValue);
		if (2 == GetHigh(pNode->rTree) - GetHigh(pNode->lTree))
		{
			if (GetHigh(pNode->rTree) > GetHigh(pNode->lTree)) // 右右情况 单旋转
				SignelRotateRightRight(pNode);
			else
				DoubleRotateRightLeft(pNode); // 右走情况
		}
	}
	else
	{
		RemoveNode(pNode->lTree, nValue); // 左子树查找
		if (2 == GetHigh(pNode->lTree) - GetHigh(pNode->rTree))
		{
			if (GetHigh(pNode->lTree) > GetHigh(pNode->rTree)) // 左左情况
				SignelRotateLeftLeft(pNode);
			else
				DoubleRotateLeftRight(pNode); // 左右情况
		}
	}
	pNode->nHigh = Max(GetHigh(pNode->lTree), GetHigh(pNode->rTree)) + 1;
	return true;
}

bool CBalanceTree::FindData(int nValue)
{
	return FindNode(m_pRoot, nValue);
}

bool CBalanceTree::FindNode(TreeNode* pNode, int nValue)
{
	if (!pNode)
		return false;
	if (nValue < pNode->lTree->nData) // 左子树查找
		FindNode(pNode->lTree, nValue);
	else if (nValue > pNode->rTree->nData)
		FindNode(pNode->rTree, nValue);
	else // 找到
		return true;
}

void CBalanceTree::BreadthTraversal() // 层序遍历
{
	if (!m_pRoot)
		return;
	std::queue<TreeNode*> queueTreeNode;
	queueTreeNode.push(m_pRoot);
	while (!queueTreeNode.empty())
	{
		TreeNode* pNode = queueTreeNode.front();
		std::cout << pNode->nData << "\t";
		queueTreeNode.pop();
		if (pNode->lTree)
			queueTreeNode.push(pNode->lTree);
		if (pNode->rTree)
			queueTreeNode.push(pNode->rTree);
	}
}

void CBalanceTree::MiddleTraversal() // 中序遍历
{
	MiddleTraversal(m_pRoot);
}

void CBalanceTree::MiddleTraversal(TreeNode* pNode)
{
	if (!pNode)
		return;
	std::cout << pNode->nData << "\t";
	MiddleTraversal(pNode->lTree);
	MiddleTraversal(pNode->rTree);
}

void CBalanceTree::DeleteNode(TreeNode*& pNode)
{
	if (!pNode)
		return;
	DeleteNode(pNode->lTree);
	DeleteNode(pNode->rTree);
	delete pNode;
	pNode = NULL;
}

测试代码:

#include "BalanceTree.h"

int main()
{
	CBalanceTree balanceTree;
	balanceTree.InsertNode(15);
	balanceTree.InsertNode(10);
	balanceTree.InsertNode(8);
	balanceTree.InsertNode(17);
	balanceTree.InsertNode(11);
	balanceTree.InsertNode(16);
	balanceTree.InsertNode(7);
	balanceTree.InsertNode(9);

	balanceTree.RemoveNode(10);
	balanceTree.BreadthTraversal();
	return 0;
}
    原文作者:平衡二叉树
    原文地址: https://blog.csdn.net/li2818/article/details/72771544
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞