C++ 自平衡二叉搜索树的实现

 C++ 自平衡二叉搜索树的实现

头文件

// AVLTree.h  for class avltree

#ifndef AVLTREE_H__________
#define AVLTREE_H__________
//#include <AFX.H>

typedef int BOOL;
#define NULL 0
#define TRUE 1
#define FALSE 0
typedef int ElemType;
struct TreeNode    // AVL树数据结构
{
	ElemType data;
	int color;
	struct TreeNode *parent;
	struct TreeNode *left;
	struct TreeNode *right;

	TreeNode(ElemType val);
	int GetLeftHight();
	int GetRightHight();
	int GetDiffHight();
	void GetNodes(TreeNode *pNode, int h);
};

// 栈类 用于存放查找结点的路径,便于回溯找到最小不平衡结点
class CStack
{
public:
	CStack(int nMaxSize = 100);
	~CStack();

	BOOL Pop(TreeNode *& node);
	BOOL Push(TreeNode * node);
	BOOL Top(TreeNode *&node);
	BOOL GetNext(TreeNode* &node);
	int Size()const{return m_nCount; }

private:
	int m_nCount;
	int m_nCurPos;
	int m_nMaxSize;
	TreeNode* *m_arrNode;  // 存放数据结点
};

// AVL树类 自平衡二叉搜索树
class CAVLTree
{
public:
	CAVLTree();
	~CAVLTree();

	int Insert(ElemType val);
	int Remove(ElemType val);
	TreeNode* Find(const ElemType &val);
	void DoBalance(TreeNode *& pCurNode, TreeNode *& pParent, int nLRFlag);
	void PrintTree();
	void EmptyTree();
	int GetSize()const { return m_nSize; }

private:
	void GetNoBalanceNode(CStack &st, TreeNode *& pCurNode, TreeNode *& pParent, int &nLRFlag);
	BOOL LL_Rotate(TreeNode *& pCurNode, TreeNode *& pParentNode, const int &nLRFlag);
	BOOL LR_Rotate(TreeNode *& pCurNode, TreeNode *& pParentNode, const int &nLRFlag);
	BOOL RR_Rotate(TreeNode *& pCurNode, TreeNode *& pParentNode, const int &nLRFlag);
	BOOL RL_Rotate(TreeNode *& pCurNode, TreeNode *& pParentNode, const int &nLRFlag);
	void PrintTree(TreeNode *& pNode);
	void GetNodes(CStack &st, TreeNode *pNode);
	void SwapNodes(TreeNode *&pNode1, TreeNode *&pNode2);

private:
	TreeNode *m_root;
	int m_nSize;
};

#endif


 

实现文件

// AVLTree.cpp  for implete class CAVLTree
#include <iostream>
#include "AVLTree.h"
#include <Windows.h>
using namespace std;
///

/// constructure functions

 struct TreeNode implete
//
TreeNode::TreeNode( ElemType val )  // 构造函数
{
	data = val;
	left = NULL;
	right = NULL;
	parent = NULL;
	color = 0;
}
int nHight = 0;

int TreeNode::GetLeftHight()
{ // 获取结点左子树高度
	nHight = 0;
	GetNodes(this->left, 0);
	return nHight;
}

int TreeNode::GetRightHight()
{  // 获取结点右子树高度
	nHight = 0;
	GetNodes(this->right, 0);
	return nHight;
}

int TreeNode::GetDiffHight()
{  // 获取结点左右子树高度的差,当放回值的绝对值大于1时,该结点为不平衡结点,需要进行结点的自平衡处理
	return (GetLeftHight() - GetRightHight());
}

void TreeNode::GetNodes(TreeNode *pNode, int h)
{ // 递归直到搜索到叶子结点,取最大的值为某结点到叶子结点的高度
	if (pNode == NULL)
	{
		nHight = (nHight > h)? nHight:h;
		return;
	}
	h++;
	GetNodes(pNode->left, h);
	GetNodes(pNode->right, h);
}

/ class CStack implete
/

CStack::CStack( int nMaxSize )  // 构造函数
{
	m_nCount = 0;
	m_nMaxSize = nMaxSize;
	m_arrNode = new TreeNode *[m_nMaxSize];
}

CStack::~CStack()  // 析构函数
{
	delete []m_arrNode;
}

BOOL CStack::Pop( TreeNode *& node )  // 出栈
{
	if (m_nCount <= 0)
		return FALSE;
	m_nCount--;
	node = m_arrNode[m_nCount];
	return TRUE;
}

BOOL CStack::Push( TreeNode * node )  // 进栈
{
	if(m_nCount < m_nMaxSize-1)
	{
		m_arrNode[m_nCount] = node;
		m_nCount++;
		return TRUE;
	}
	return FALSE;
}

BOOL CStack::Top( TreeNode *&node )  // 获取栈顶值
{
	if (m_nCount > 0)
	{
		node = m_arrNode[m_nCount-1];
		m_nCurPos = m_nCount - 1;
		return TRUE;
	}
	return FALSE;
}

BOOL CStack::GetNext( TreeNode* &node ) // 第一次返回的值为栈顶的下一数值
{
	if (m_nCurPos-1 < m_nCount-1 && m_nCurPos-1 >= 0)
	{
		m_nCurPos--;
		node = m_arrNode[m_nCurPos];
		return TRUE;
	}
	return FALSE;
}


/ class CAVLTree implete
//
CAVLTree::CAVLTree()  // 构造函数
{
	m_root = NULL;
	m_nSize = 0;
}

CAVLTree::~CAVLTree()
{
	EmptyTree();  //释放该树结构所有结点
}

int CAVLTree::Insert( ElemType val )  // 插入树结点
{
	CStack stNodes(100000);
	TreeNode *pNewNode = new TreeNode(val);
	TreeNode *pNode = m_root;
	TreeNode *preNode = NULL;
	int nFlag;  // 0--left 1--right
	if (m_root == NULL)
	{  // 该树为空
		m_root = pNewNode;
		cout<< "Insert root node: " << pNewNode->data <<" succeed." <<endl;
	//	Sleep(500);
		m_nSize++;
		return 1;
	}
	while(1)
	{   // 查找要插入的位置
		preNode = pNode;
		if (val < pNode->data)
		{
			stNodes.Push(pNode);
			pNode = pNode->left;
			nFlag = 0;
		}
		else if (val > pNode->data)
		{
			stNodes.Push(pNode);
			pNode = pNode->right;
			nFlag = 1;
		}
		else 
		{
			delete pNewNode;
			return 0;
		}

		if (!pNode) //页子结点
		{
			if (nFlag == 0)
			{
				preNode->left = pNewNode;
			}
			else
				preNode->right = pNewNode;
	//		Sleep(500);
			break;
		}
	}
	TreeNode *pNBLNode = NULL;
	TreeNode *pNBLParent = NULL;
	nFlag = 0;
	GetNoBalanceNode(stNodes, pNBLNode, pNBLParent, nFlag);
	if (pNBLNode)
	{
		DoBalance(pNBLNode, pNBLParent, nFlag);
	}
	m_nSize++;
	cout<< "Insert "<< m_nSize <<" node: " << pNewNode->data <<" succeed." <<endl; 
	return 1;
}

int CAVLTree::Remove( ElemType val )  // 删除某一结点
{
	if (!m_root) return 0;
	CStack stNodes(100000);  // 记录查找的路径结点
	TreeNode *pNode = m_root;
	TreeNode *pPreNode = m_root;
	int nLRFlag;
	while(pNode)
	{
		if (val < pNode->data)
		{
			stNodes.Push(pNode);
			if (pNode->left)
			{
				pPreNode = pNode;
			}
			pNode = pNode->left;
			nLRFlag = 0;
		}
		else if (val > pNode->data)
		{
			stNodes.Push(pNode);
			if (pNode->right)
			{
				pPreNode = pNode;
			}
			pNode = pNode->right;
			nLRFlag = 1;
		}
		else break;	
	}
	if (!pNode)   //没找到要删除的结点
		return 0;
	if (!stNodes.Top(pPreNode))
	{ // tree has only one root node.
		pPreNode = NULL;
		if (pNode->left == NULL && pNode->right == NULL)
		{
			delete pNode;
			m_root = NULL;
			m_nSize--;
			return 1;
		}
	}
	if (pNode->left)  //pNode为要删除的结点
	{ // 寻找该结点的左子树中最大的结点与之交换位置
		TreeNode *pNodeDel = pNode->left;
		TreeNode *pPre = pNode;
		stNodes.Push(pPre);
		while(pNodeDel->right)
		{
			pPre = pNodeDel;
			stNodes.Push(pPre);
			pNodeDel = pNodeDel->right;
		}
		SwapNodes(pNode, pNodeDel);  // 将要删除的结点与符合要求的叶子结点交换,然后删除该叶子结点
		if (pPre->left == pNodeDel)// pNode 左边只有一个叶子结点
		{
			pPre->left = pNodeDel->left;
		}
		else
			pPre->right = pNodeDel->left;

		delete pNodeDel;  // 释放叶子结点
	}
	else if (pNode->right)
	{ // 寻找该结点的右子树中最小的结点与之交换位置
		TreeNode *pNodeDel = pNode->right;
		TreeNode *pPre = pNode;
		stNodes.Push(pPre);
		while(pNodeDel->left)
		{
			pPre = pNodeDel;
			stNodes.Push(pPre);
			pNodeDel = pNodeDel->left;
		}
		SwapNodes(pNode, pNodeDel);
		pPre->right = pNodeDel->left;

		delete pNodeDel;
	}
	else  // 该结点为叶子结点
	{
		delete pNode;
		if (nLRFlag == 0)
		{
			pPreNode->left = NULL;
		}
		else
			pPreNode->right = NULL;
	}
	cout << "Remove node: " << val << " succeeded!\n";
//	Sleep(500);
	/// 检查不平衡结点
	TreeNode *pNBLNode = NULL;
	TreeNode *pPreNBLNode = NULL;
	nLRFlag = 0;
	GetNoBalanceNode(stNodes, pNBLNode, pPreNBLNode, nLRFlag);
	if (pNBLNode)
	{
		DoBalance(pNBLNode, pPreNBLNode, nLRFlag);
	}
	m_nSize--;
	return 1;	
}

TreeNode* CAVLTree::Find( const ElemType &val )  // 查找某一结点
{
	if (m_root == NULL) return NULL;
	TreeNode *pNode = m_root;
	while (pNode)
	{
		if (pNode->data < val)
		{
			pNode = pNode->right;
		}
		else if (pNode->data > val)
		{
			pNode = pNode->left;
		}
		else
		{
			cout << "Find node: " << val << " succeeded!\n";
			return pNode;
		}
	}
	return NULL;	
}

// 获取不平衡的结点的信息
void CAVLTree::GetNoBalanceNode( CStack &st, TreeNode *& pCurNode, TreeNode *& pParent, int &nLRFlag )
{
	TreeNode *pNode;
	if (!st.Top(pNode))	return ;
	while(1)
	{
		int nDiff = pNode->GetDiffHight();
		if (nDiff > 1 || nDiff < -1)
		{
			pCurNode = pNode;
			if (st.GetNext(pParent))
			{
				if (pParent->left == pCurNode)
				{
					nLRFlag = 0;  // left child
				}
				else /*if (pParent->right == pCurNode)*/
				{
					nLRFlag = 1;  // right child
				}
				return ;
			}
		}
		if (!st.GetNext(pNode))
		{
			return ;
		}
	}
}

// 自平衡处理函数
void CAVLTree::DoBalance( TreeNode *& pCurNode, TreeNode *& pParent, int nLRFlag )
{
	cout << "Call DoBalance() succeeded!\n";
	if (pCurNode->GetLeftHight() > pCurNode->GetRightHight())
	{
		if (pCurNode->left->GetLeftHight() > pCurNode->left->GetRightHight())
		{
			LL_Rotate(pCurNode, pParent, nLRFlag);  // LR型 平衡处理
		}
		else
			LR_Rotate(pCurNode, pParent, nLRFlag);  // LL型 平衡处理
	}
	else
	{
		if (pCurNode->right->GetLeftHight() > pCurNode->right->GetRightHight())
		{
			RL_Rotate(pCurNode, pParent, nLRFlag);  // RL型 平衡处理
		}
		else
			RR_Rotate(pCurNode, pParent, nLRFlag);  // RR型 平衡处理
	}
}

BOOL CAVLTree::LL_Rotate( TreeNode *& pCurNode, TreeNode *& pParentNode, const int &nLRFlag )
{
	cout << "Call LL_Rotate() succeeded!\n";
	TreeNode *pTempRoot = pCurNode->left;
	TreeNode *pTempRootR = pTempRoot->right;
	pTempRoot->right = pCurNode;
	pCurNode->left = pTempRootR;
	if (pParentNode)
	{
		if (nLRFlag == 0)
		{
			pParentNode->left = pTempRoot;
		}
		else
			pParentNode->right = pTempRoot;
	}
	else  // root
		m_root = pTempRoot;
	
	return TRUE;
}

BOOL CAVLTree::LR_Rotate( TreeNode *& pCurNode, TreeNode *& pParentNode, const int &nLRFlag )
{
	cout << "Call LR_Rotate() run succeeded!\n";
	TreeNode *pNodeA = pCurNode->left;
	TreeNode *pNodeB = pNodeA->right;
	TreeNode *pPreB = pNodeA;
	TreeNode *pTempRoot = NULL;
	while(pNodeB->right)
	{
		pPreB = pNodeB;
		pNodeB = pNodeB->right;
	}
	pTempRoot = pNodeB;
	if (pTempRoot == NULL)   // pNodeA 的右子树为空
	{
		pTempRoot = pNodeA;
		pTempRoot->right = pCurNode;
		pCurNode->left = NULL;
	}
	else
	{
		pPreB->right = pTempRoot->left;
		pTempRoot->left = pNodeA;
		pTempRoot->right = pCurNode;
		pCurNode->left = NULL;
	}
	if (pParentNode)
	{
		if (nLRFlag == 0)
		{
			pParentNode->left = pTempRoot;
		}
		else
			pParentNode->right = pTempRoot;
	}
	else  // root
		m_root = pTempRoot;

	
	return TRUE;
}

BOOL CAVLTree::RR_Rotate( TreeNode *& pCurNode, TreeNode *& pParentNode, const int &nLRFlag )
{
	cout << "Call RR_Rotate() succeeded!\n";
	TreeNode *pTempRoot = pCurNode->right;
	TreeNode *pTempRootL = pTempRoot->left;
	pTempRoot->left = pCurNode;
	pCurNode->right = pTempRootL;
	if (pParentNode)
	{
		if (nLRFlag == 0)
		{
			pParentNode->left = pTempRoot;
		}
		else
			pParentNode->right = pTempRoot;
	}
	else  // root
		m_root = pTempRoot;
	
	return TRUE;
}

BOOL CAVLTree::RL_Rotate( TreeNode *& pCurNode, TreeNode *& pParentNode, const int &nLRFlag )
{
	cout << "Call RL_Rotate() run succeeded!\n";
	TreeNode *pNodeA = pCurNode->right;
	TreeNode *pNodeB = pNodeA->left;
	TreeNode *pPreB = pNodeA;
	while(pNodeB->left)
	{
		pPreB = pNodeB;
		pNodeB = pPreB->left;
	}
	TreeNode *pTempRoot = pNodeB;
	if (pTempRoot == NULL)
	{
		pTempRoot = pNodeA;
		pCurNode->right = NULL;
		pTempRoot->left = pCurNode;
	}
	else
	{
		pTempRoot->left = pCurNode;
		pCurNode->right = NULL;
		pPreB->left = pTempRoot->right;
		pTempRoot->right = pNodeA;
	}

	if (pParentNode)
	{
		if (nLRFlag == 0)
		{
			pParentNode->left = pTempRoot;
		}
		else
			pParentNode->right = pTempRoot;
	}
	else  // root
		m_root = pTempRoot;
	
	
	return TRUE;
}

void CAVLTree::PrintTree()   // 打印树结点
{
	if (!m_root)
	{
		cout << "The tree is empty!\n";
		return ;
	}
	PrintTree(m_root);  // 调用递归遍历结点函数
	cout << endl;
}

void CAVLTree::PrintTree( TreeNode *& pNode )
{
	if (pNode)
	{
		cout << pNode->data << "  ";
		PrintTree(pNode->left);
		PrintTree(pNode->right);
	}
}

void CAVLTree::EmptyTree()  // 清空结点,释放结点空间
{
	if (!m_root)
	{
		return;
	}
	CStack stNodes(10000);
	GetNodes(stNodes, m_root);
	TreeNode *pTemp;
	if (stNodes.Pop(pTemp))
	{
		delete pTemp;
	}
	m_root = NULL;
	cout << "Emptied the tree succeeded!\n";
}

void CAVLTree::GetNodes( CStack &st, TreeNode *pNode )
{
	if (pNode)
	{
		GetNodes(st, pNode->left);
		GetNodes(st, pNode->right);
	}
}

void CAVLTree::SwapNodes( TreeNode *&pNode1, TreeNode *&pNode2 )  // 交换两个结点
{
	ElemType val = pNode1->data;
	pNode1->data = pNode2->data;
	pNode2->data = val;
}


 

测试文件

/// test.cpp for test the class CAVLTree
#include <iostream>
#include "AVLTree.h"
#include <ctime>
using namespace std;

void LL_Test();
void RR_Test();
void LR_Test();
void RL_Test();
void time_Test();
void main()
{
	time_Test();
// 	LL_Test();
// 	RR_Test();
//	LR_Test();
//	RL_Test();
	return;
}

void time_Test()
{
	cout << "time_Test Function.\n";
	CAVLTree tree;
	clock_t t_insert, t_print, t_find;  // 分别记录插入数据时间和打印数据时间
	int nArrNodes[30000];
	srand((unsigned)time(NULL));
//	srand(0);
	t_insert = clock();
	for (int i = 0; i < 30000; i++)
	{
		nArrNodes[i] = rand();
		while (1)
		{
			if (tree.Find(nArrNodes[i]) == NULL)
			{
				tree.Insert(nArrNodes[i]);
				break;
			}
			else
				nArrNodes[i] = rand();
		}	
	}
	t_insert = clock() - t_insert;
	t_print = clock();
	tree.PrintTree();
	t_print = clock() - t_print;
	t_find = clock();
	tree.Find(32725);
	t_find = clock() - t_find;
	cout << "The tree nodes count is: " << tree.GetSize() << endl;
	cout << "Insert data need time: " << t_insert << "ms." << endl;
	cout << "Print data need time: " << t_print << "ms." << endl;
	cout << "Find one data need time: " << t_find << "ms." << endl;
}

void LL_Test()
{
	cout << "/LL_Test" << endl;
	CAVLTree tree;
	tree.Insert(9);
	tree.Insert(5);
	tree.Insert(11);
	tree.Insert(6);
	tree.Insert(15);
	tree.Insert(4);
	tree.Insert(3);
	tree.PrintTree();
	tree.Remove(9);
	tree.PrintTree();
	cout << endl;
	return;
}

void RR_Test()
{
	cout << "//RR_Test" << endl;
	CAVLTree tree;
	tree.Insert(4);
	tree.Insert(2);
	tree.Insert(6);
	tree.Insert(5);
	tree.Insert(9);
	tree.Insert(11);
	tree.PrintTree();
	cout << endl;
	return;
}

void LR_Test()
{
	cout << "LR_Test" << endl;
	CAVLTree tree;
	tree.Insert(9);
	tree.Insert(4);
	tree.Insert(11);
	tree.Insert(2);
	tree.Insert(6);
	tree.Insert(5);
	tree.PrintTree();
	tree.Remove(6);
	tree.PrintTree();
	cout << endl;
	return;
}

void RL_Test()
{
	cout << "//RL_Test" << endl;
	CAVLTree tree;
	tree.Insert(4);
	tree.Insert(2);
	tree.Insert(9);
	tree.Insert(6);
	tree.Insert(11);
	tree.Insert(5);
	tree.PrintTree();
	tree.Insert(7);
	tree.Insert(8);
	tree.PrintTree();
	tree.Remove(6);
	tree.PrintTree();
	tree.Remove(11);
	tree.PrintTree();
	tree.Remove(7);
	tree.PrintTree();
	tree.Remove(8);
	tree.PrintTree();
	tree.Remove(9);
	tree.PrintTree();
	tree.Remove(4);
	tree.PrintTree();
	tree.Remove(2);
	tree.PrintTree();
	tree.Remove(5);
	tree.PrintTree();
	cout << endl;
	return;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值