平衡二叉树实现(Balanced Binary Tree)

平衡二叉树(Balanced Binary Tree)是二叉查找树的一个进化体,也是第一个引入平衡概念的二叉树。1962年,G.M. Adelson-Velsky 和 E.M. Landis发明了这棵树,所以它又叫AVL树。

平衡二叉树要求对于每一个节点来说,它的左右子树的高度之差不能超过1,如果插入或者删除一个节点使得高度之差大于1,就要进行节点之间的旋转,将二叉树重新维持在一个平衡状态。这个方案很好的解决了二叉查找树退化成链表的问题,把插入,查找,删除的时间复杂度最好情况和最坏情况都维持在O(logN)。

但是频繁旋转会使插入和删除牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了很多。

平衡二叉树实现的大部分过程和二叉查找树是一样的(学平衡二叉树之前一定要会二叉查找树),区别就在于插入和删除之后要写一个旋转算法去维持平衡,维持平衡需要借助一个节点高度的属性。

讲解视频:链接:https://pan.baidu.com/s/1w5hlEwgbG7qFF7ZJr52QmA 提取码:mhmw

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
#pragma once
//二叉树节点
template<class T>
struct BinaryNode
{
T mValue;
int mHeight; //树的高度
BinaryNode<T>* pLchild; //指向左子树节点
BinaryNode<T>* pRchild; //指向右子树节点
BinaryNode<T>* pParent; //指向父节点
};
template<class T>
class BinarySearchTree
{
public:
// 构造函数
BinarySearchTree();
// 析构函数
~BinarySearchTree();
// 拷贝构造函数
BinarySearchTree(const BinarySearchTree<T>& bst);
//插入
void Insert(const T& val);
//查找
BinaryNode<T>* SearchNode(const T& val);
// 中序遍历
template<class _Func>
void Foreach(_Func func);
// 辅助中序遍历
template<class _Func>
void MyForeach(BinaryNode<T>* root, _Func func);
//释放二叉树
void MyFree(BinaryNode<T>* root)l;
//拷贝二叉树
BinaryNode<T>* MyCopy(BinaryNode<T>* root, BinaryNode<T>* parent = NULL);
//删除算法
void Remove(const T& val);
//第一种情况,如果删除的结点是叶子节点
void RemoveNoChildNode(BinaryNode<T>* delNode);
//第二种情况,如果删除的结点只有一个孩子
void RemoveSingleChildNode(BinaryNode<T>* delNode);
//第三种情况,如果删除的结点有两个孩子
void RemoveDoubleChildNode(BinaryNode<T>* delNode);
//获得最大值结点
BinaryNode<T>* GetMaxNode(BinaryNode<T>* root);
//获得最小值结点
BinaryNode<T>* GetMinNode(BinaryNode<T>* root);
/* 平衡二叉树接口 */
//更新树的高度
int UpdateTreeHeight(BinaryNode<T>* root);
//获得某个子树的高度
int GetTreeHeight(BinaryNode<T>* node);
//求某个子树的平衡因子
int GetBalanceFactor(BinaryNode<T>* node);
// 右旋
void RightRotate(BinaryNode<T>* node);
// 左旋
void leftRotate(BinaryNode<T>* node);
// 调整树的平衡(subRoot)
void AdjustTreeBalance(BinaryNode<T>* subRoot);
public:
BinaryNode<T>* pRoot; //永远指向二叉排序树的根节点
int mSize;
};
#pragma once //二叉树节点 template<class T> struct BinaryNode { T mValue; int mHeight; //树的高度 BinaryNode<T>* pLchild; //指向左子树节点 BinaryNode<T>* pRchild; //指向右子树节点 BinaryNode<T>* pParent; //指向父节点 }; template<class T> class BinarySearchTree { public: // 构造函数 BinarySearchTree(); // 析构函数 ~BinarySearchTree(); // 拷贝构造函数 BinarySearchTree(const BinarySearchTree<T>& bst); //插入 void Insert(const T& val); //查找 BinaryNode<T>* SearchNode(const T& val); // 中序遍历 template<class _Func> void Foreach(_Func func); // 辅助中序遍历 template<class _Func> void MyForeach(BinaryNode<T>* root, _Func func); //释放二叉树 void MyFree(BinaryNode<T>* root)l; //拷贝二叉树 BinaryNode<T>* MyCopy(BinaryNode<T>* root, BinaryNode<T>* parent = NULL); //删除算法 void Remove(const T& val); //第一种情况,如果删除的结点是叶子节点 void RemoveNoChildNode(BinaryNode<T>* delNode); //第二种情况,如果删除的结点只有一个孩子 void RemoveSingleChildNode(BinaryNode<T>* delNode); //第三种情况,如果删除的结点有两个孩子 void RemoveDoubleChildNode(BinaryNode<T>* delNode); //获得最大值结点 BinaryNode<T>* GetMaxNode(BinaryNode<T>* root); //获得最小值结点 BinaryNode<T>* GetMinNode(BinaryNode<T>* root); /* 平衡二叉树接口 */ //更新树的高度 int UpdateTreeHeight(BinaryNode<T>* root); //获得某个子树的高度 int GetTreeHeight(BinaryNode<T>* node); //求某个子树的平衡因子 int GetBalanceFactor(BinaryNode<T>* node); // 右旋 void RightRotate(BinaryNode<T>* node); // 左旋 void leftRotate(BinaryNode<T>* node); // 调整树的平衡(subRoot) void AdjustTreeBalance(BinaryNode<T>* subRoot); public: BinaryNode<T>* pRoot; //永远指向二叉排序树的根节点 int mSize; };
#pragma once

//二叉树节点
template<class T>
struct BinaryNode
{
	T mValue;
	int mHeight; //树的高度
	BinaryNode<T>* pLchild; //指向左子树节点
	BinaryNode<T>* pRchild; //指向右子树节点
	BinaryNode<T>* pParent; //指向父节点
};


template<class T>
class BinarySearchTree
{
public:
	// 构造函数
	BinarySearchTree();
	// 析构函数
	~BinarySearchTree();
	// 拷贝构造函数
	BinarySearchTree(const BinarySearchTree<T>& bst);

	//插入
	void Insert(const T& val);
	//查找
	BinaryNode<T>* SearchNode(const T& val);

	// 中序遍历
	template<class _Func>
	void Foreach(_Func func);
	// 辅助中序遍历
	template<class _Func>
	void MyForeach(BinaryNode<T>* root, _Func func);

	//释放二叉树
	void MyFree(BinaryNode<T>* root)l;
	//拷贝二叉树
	BinaryNode<T>* MyCopy(BinaryNode<T>* root, BinaryNode<T>* parent = NULL);

	//删除算法
	void Remove(const T& val);
	//第一种情况,如果删除的结点是叶子节点
	void RemoveNoChildNode(BinaryNode<T>* delNode);
	//第二种情况,如果删除的结点只有一个孩子
	void RemoveSingleChildNode(BinaryNode<T>* delNode);
	//第三种情况,如果删除的结点有两个孩子
	void RemoveDoubleChildNode(BinaryNode<T>* delNode);

	//获得最大值结点
	BinaryNode<T>* GetMaxNode(BinaryNode<T>* root);
	//获得最小值结点
	BinaryNode<T>* GetMinNode(BinaryNode<T>* root);
	/* 平衡二叉树接口 */
	//更新树的高度
	int UpdateTreeHeight(BinaryNode<T>* root);
	//获得某个子树的高度
	int GetTreeHeight(BinaryNode<T>* node);
	//求某个子树的平衡因子
	int GetBalanceFactor(BinaryNode<T>* node);
	// 右旋
	void RightRotate(BinaryNode<T>* node);
	// 左旋
	void leftRotate(BinaryNode<T>* node);
	// 调整树的平衡(subRoot)
	void AdjustTreeBalance(BinaryNode<T>* subRoot);

public:
	BinaryNode<T>* pRoot; //永远指向二叉排序树的根节点
	int mSize;
};

1. 初始化和销毁

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// 构造函数
template<class T>
BinarySearchTree<T>::BinarySearchTree()
{
pRoot = NULL;
mSize = 0;
}
// 析构函数
template<class T>
BinarySearchTree<T>::~BinarySearchTree()
{
MyFree(pRoot);
}
// 拷贝构造
template<class T>
BinarySearchTree<T>::BinarySearchTree(const BinarySearchTree<T>& bst)
{
mSize = bst.mSize;
pRoot = MyCopy(bst.pRoot, NULL);
}
//释放二叉树
template<class T>
void BinarySearchTree<T>::MyFree(BinaryNode<T>* root)
{
if (NULL == root)
{
return;
}
//释放左子树内存
MyFree(root->pLchild);
//释放右子树内存
MyFree(root->pRchild);
//释放当前结点的内存
delete root;
}
//拷贝二叉树
template<class T>
BinaryNode<T>* BinarySearchTree<T>::MyCopy(BinaryNode<T>* root, BinaryNode<T>* parent = NULL)
{
if (NULL == root)
{
return NULL;
}
//拷贝当前结点
BinaryNode<T>* newnode = new BinaryNode<T>;
newnode->mValue = root->mValue;
newnode->pParent = parent;
newnode->pLchild = NULL;
newnode->pRchild = NULL;
//拷贝左子树
BinaryNode<T>* pLeft = MyCopy(root->pLchild, newnode);
//拷贝右子树
BinaryNode<T>* pRight = MyCopy(root->pRchild, newnode);
//更新新节点的左右指针指向
newnode->pLchild = pLeft;
newnode->pRchild = pRight;
return newnode;
}
// 构造函数 template<class T> BinarySearchTree<T>::BinarySearchTree() { pRoot = NULL; mSize = 0; } // 析构函数 template<class T> BinarySearchTree<T>::~BinarySearchTree() { MyFree(pRoot); } // 拷贝构造 template<class T> BinarySearchTree<T>::BinarySearchTree(const BinarySearchTree<T>& bst) { mSize = bst.mSize; pRoot = MyCopy(bst.pRoot, NULL); } //释放二叉树 template<class T> void BinarySearchTree<T>::MyFree(BinaryNode<T>* root) { if (NULL == root) { return; } //释放左子树内存 MyFree(root->pLchild); //释放右子树内存 MyFree(root->pRchild); //释放当前结点的内存 delete root; } //拷贝二叉树 template<class T> BinaryNode<T>* BinarySearchTree<T>::MyCopy(BinaryNode<T>* root, BinaryNode<T>* parent = NULL) { if (NULL == root) { return NULL; } //拷贝当前结点 BinaryNode<T>* newnode = new BinaryNode<T>; newnode->mValue = root->mValue; newnode->pParent = parent; newnode->pLchild = NULL; newnode->pRchild = NULL; //拷贝左子树 BinaryNode<T>* pLeft = MyCopy(root->pLchild, newnode); //拷贝右子树 BinaryNode<T>* pRight = MyCopy(root->pRchild, newnode); //更新新节点的左右指针指向 newnode->pLchild = pLeft; newnode->pRchild = pRight; return newnode; }
// 构造函数
template<class T>
BinarySearchTree<T>::BinarySearchTree()
{
	pRoot = NULL;
	mSize = 0;
}

// 析构函数
template<class T>
BinarySearchTree<T>::~BinarySearchTree()
{
	MyFree(pRoot);
}

// 拷贝构造
template<class T>
BinarySearchTree<T>::BinarySearchTree(const BinarySearchTree<T>& bst)
{
	mSize = bst.mSize;
	pRoot = MyCopy(bst.pRoot, NULL);
}

//释放二叉树
template<class T>
void BinarySearchTree<T>::MyFree(BinaryNode<T>* root)
{
	if (NULL == root)
	{
		return;
	}

	//释放左子树内存
	MyFree(root->pLchild);
	//释放右子树内存
	MyFree(root->pRchild);
	//释放当前结点的内存
	delete root;
}

//拷贝二叉树
template<class T>
BinaryNode<T>* BinarySearchTree<T>::MyCopy(BinaryNode<T>* root, BinaryNode<T>* parent = NULL)
{
	if (NULL == root)
	{
		return NULL;
	}

	//拷贝当前结点
	BinaryNode<T>* newnode = new BinaryNode<T>;
	newnode->mValue = root->mValue;
	newnode->pParent = parent;

	newnode->pLchild = NULL;
	newnode->pRchild = NULL;

	//拷贝左子树
	BinaryNode<T>* pLeft = MyCopy(root->pLchild, newnode);
	//拷贝右子树
	BinaryNode<T>* pRight = MyCopy(root->pRchild, newnode);

	//更新新节点的左右指针指向
	newnode->pLchild = pLeft;
	newnode->pRchild = pRight;

	return newnode;
}

2. 遍历函数

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
template<class T> template<class _Func>
void BinarySearchTree<T>::Foreach(_Func func)
{
MyForeach(pRoot, func);
}
//辅助中序遍历
template<class T> template<class _Func>
void BinarySearchTree<T>::MyForeach(BinaryNode<T>* root, _Func func)
{
if (NULL == root)
{
return;
}
MyForeach(root->pLchild, func);
func(root->mValue);
MyForeach(root->pRchild, func);
}
template<class T> template<class _Func> void BinarySearchTree<T>::Foreach(_Func func) { MyForeach(pRoot, func); } //辅助中序遍历 template<class T> template<class _Func> void BinarySearchTree<T>::MyForeach(BinaryNode<T>* root, _Func func) { if (NULL == root) { return; } MyForeach(root->pLchild, func); func(root->mValue); MyForeach(root->pRchild, func); }
template<class T> template<class _Func>
void BinarySearchTree<T>::Foreach(_Func func)
{
	MyForeach(pRoot, func);
}

//辅助中序遍历
template<class T> template<class _Func>
void BinarySearchTree<T>::MyForeach(BinaryNode<T>* root, _Func func)
{
	if (NULL == root)
	{
		return;
	}
	MyForeach(root->pLchild, func);
	func(root->mValue);
	MyForeach(root->pRchild, func);
}

3. 查找函数

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
template<class T>
BinaryNode<T>* BinarySearchTree<T>::SearchNode(const T& val)
{
//辅助指针变量
BinaryNode<T>* pCurrent = pRoot;
while (pCurrent != NULL)
{
if (val < pCurrent->mValue)
{
pCurrent = pCurrent->pLchild;
}
else if (!(val < pCurrent->mValue) && !(pCurrent->mValue < val))
{
return pCurrent;
}
else
{
pCurrent = pCurrent->pRchild;
}
}
return NULL;
}
template<class T> BinaryNode<T>* BinarySearchTree<T>::SearchNode(const T& val) { //辅助指针变量 BinaryNode<T>* pCurrent = pRoot; while (pCurrent != NULL) { if (val < pCurrent->mValue) { pCurrent = pCurrent->pLchild; } else if (!(val < pCurrent->mValue) && !(pCurrent->mValue < val)) { return pCurrent; } else { pCurrent = pCurrent->pRchild; } } return NULL; }
template<class T>
BinaryNode<T>* BinarySearchTree<T>::SearchNode(const T& val)
{
	//辅助指针变量
	BinaryNode<T>* pCurrent = pRoot;
	while (pCurrent != NULL)
	{
		if (val < pCurrent->mValue)
		{
			pCurrent = pCurrent->pLchild;
		}
		else if (!(val < pCurrent->mValue) && !(pCurrent->mValue < val))
		{
			return pCurrent;
		}
		else
		{
			pCurrent = pCurrent->pRchild;
		}
	}

	return NULL;
}

4. 树高度函数

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
//获得子树的高度
template<class T>
int BinarySearchTree<T>::GetTreeHeight(BinaryNode<T>* node)
{
if (NULL == node)
{
return 0;
}
return node->mHeight;
}
//求某个子树的平衡因子
template<class T>
int BinarySearchTree<T>::GetBalanceFactor(BinaryNode<T>* node)
{
if (NULL == node)
{
return 0;
}
return GetTreeHeight(node->pLchild) - GetTreeHeight(node->pRchild);
}
//获得子树的高度 template<class T> int BinarySearchTree<T>::GetTreeHeight(BinaryNode<T>* node) { if (NULL == node) { return 0; } return node->mHeight; } //求某个子树的平衡因子 template<class T> int BinarySearchTree<T>::GetBalanceFactor(BinaryNode<T>* node) { if (NULL == node) { return 0; } return GetTreeHeight(node->pLchild) - GetTreeHeight(node->pRchild); }
//获得子树的高度
template<class T>
int BinarySearchTree<T>::GetTreeHeight(BinaryNode<T>* node)
{
	if (NULL == node)
	{
		return 0;
	}

	return node->mHeight;
}

//求某个子树的平衡因子
template<class T>
int BinarySearchTree<T>::GetBalanceFactor(BinaryNode<T>* node)
{
	if (NULL == node)
	{
		return 0;
	}

	return GetTreeHeight(node->pLchild) - GetTreeHeight(node->pRchild);
}

5. 树旋转操作

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
//树的旋转-向右旋转
template<class T>
void BinarySearchTree<T>::RightRotate(BinaryNode<T>* node)
{
if (NULL == node)
{
return;
}
//缓存下当前子树的根节点的父节点
BinaryNode<T>* pParent = node->pParent;
//缓存下当前子树的根节点的左子树
BinaryNode<T>* pLeftNode = node->pLchild;
node->pLchild = pLeftNode->pRchild;
if (pLeftNode->pRchild != NULL)
{
pLeftNode->pRchild->pParent = node;
}
pLeftNode->pRchild = node;
node->pParent = pLeftNode;
//备注:设置父节点
pLeftNode->pParent = pParent;
//父节点为NULL
if (pParent == NULL)
{
pRoot = pLeftNode;
}
else
{
if (pParent->pLchild == node)
{
pParent->pLchild = pLeftNode;
}
else
{
pParent->pRchild = pLeftNode;
}
}
}
//左旋
template<class T>
void BinarySearchTree<T>::leftRotate(BinaryNode<T>* node)
{
if (NULL == node)
{
return;
}
//缓存下父节点
BinaryNode<T>* pParent = node->pParent;
//缓存下右子树
BinaryNode<T>* pRight = node->pRchild;
node->pRchild = pRight->pLchild;
if (pRight->pLchild != NULL)
{
pRight->pLchild->pParent = node;
}
pRight->pLchild = node;
node->pParent = pRight;
//备注:设置父节点
pRight->pParent = pParent;
if (pParent == NULL)
{
pRoot = pRight;
}
else
{
if (pParent->pLchild == node)
{
pParent->pLchild = pRight;
}
else
{
pParent->pRchild = pRight;
}
}
}
//调整树的平衡(subRoot)
template<class T>
void BinarySearchTree<T>::AdjustTreeBalance(BinaryNode<T>* subRoot)
{
if (NULL == subRoot)
{
return;
}
//找到最小不平衡子树
BinaryNode<T>* pBack = subRoot;
//当前结点的平衡因子
int factor = 0;
while (pBack != NULL)
{
//计算当前结点的平衡因子
factor = GetBalanceFactor(pBack);
if (abs(factor) > 1)
{
break;
}
pBack = pBack->pParent;
}
if (pBack == NULL)
{
//此时树不需要调整
return;
}
if (factor > 1)
{
//右旋
if (GetBalanceFactor(pBack->pLchild) > 0)
{
//进行一次向右旋转
RightRotate(pBack);
}
else
{
//先把pBack->pLchild左旋一次
leftRotate(pBack->pLchild);
//再把pBack整体向右旋转一次
RightRotate(pBack);
}
}
else
{
//左旋
if (GetBalanceFactor(pBack->pRchild) < 0)
{
//直接向左旋转一次
leftRotate(pBack);
}
else
{
//先把pBack->pRcild向右旋转一次
RightRotate(pBack->pRchild);
//然后再把pBack整体向左旋转一次
leftRotate(pBack);
}
}
}
//树的旋转-向右旋转 template<class T> void BinarySearchTree<T>::RightRotate(BinaryNode<T>* node) { if (NULL == node) { return; } //缓存下当前子树的根节点的父节点 BinaryNode<T>* pParent = node->pParent; //缓存下当前子树的根节点的左子树 BinaryNode<T>* pLeftNode = node->pLchild; node->pLchild = pLeftNode->pRchild; if (pLeftNode->pRchild != NULL) { pLeftNode->pRchild->pParent = node; } pLeftNode->pRchild = node; node->pParent = pLeftNode; //备注:设置父节点 pLeftNode->pParent = pParent; //父节点为NULL if (pParent == NULL) { pRoot = pLeftNode; } else { if (pParent->pLchild == node) { pParent->pLchild = pLeftNode; } else { pParent->pRchild = pLeftNode; } } } //左旋 template<class T> void BinarySearchTree<T>::leftRotate(BinaryNode<T>* node) { if (NULL == node) { return; } //缓存下父节点 BinaryNode<T>* pParent = node->pParent; //缓存下右子树 BinaryNode<T>* pRight = node->pRchild; node->pRchild = pRight->pLchild; if (pRight->pLchild != NULL) { pRight->pLchild->pParent = node; } pRight->pLchild = node; node->pParent = pRight; //备注:设置父节点 pRight->pParent = pParent; if (pParent == NULL) { pRoot = pRight; } else { if (pParent->pLchild == node) { pParent->pLchild = pRight; } else { pParent->pRchild = pRight; } } } //调整树的平衡(subRoot) template<class T> void BinarySearchTree<T>::AdjustTreeBalance(BinaryNode<T>* subRoot) { if (NULL == subRoot) { return; } //找到最小不平衡子树 BinaryNode<T>* pBack = subRoot; //当前结点的平衡因子 int factor = 0; while (pBack != NULL) { //计算当前结点的平衡因子 factor = GetBalanceFactor(pBack); if (abs(factor) > 1) { break; } pBack = pBack->pParent; } if (pBack == NULL) { //此时树不需要调整 return; } if (factor > 1) { //右旋 if (GetBalanceFactor(pBack->pLchild) > 0) { //进行一次向右旋转 RightRotate(pBack); } else { //先把pBack->pLchild左旋一次 leftRotate(pBack->pLchild); //再把pBack整体向右旋转一次 RightRotate(pBack); } } else { //左旋 if (GetBalanceFactor(pBack->pRchild) < 0) { //直接向左旋转一次 leftRotate(pBack); } else { //先把pBack->pRcild向右旋转一次 RightRotate(pBack->pRchild); //然后再把pBack整体向左旋转一次 leftRotate(pBack); } } }
//树的旋转-向右旋转
template<class T>
void BinarySearchTree<T>::RightRotate(BinaryNode<T>* node)
{

	if (NULL == node)
	{
		return;
	}

	//缓存下当前子树的根节点的父节点
	BinaryNode<T>* pParent = node->pParent;
	//缓存下当前子树的根节点的左子树
	BinaryNode<T>* pLeftNode = node->pLchild;

	node->pLchild = pLeftNode->pRchild;
	if (pLeftNode->pRchild != NULL)
	{
		pLeftNode->pRchild->pParent = node;
	}


	pLeftNode->pRchild = node;
	node->pParent = pLeftNode;

	//备注:设置父节点
	pLeftNode->pParent = pParent;

	//父节点为NULL
	if (pParent == NULL)
	{
		pRoot = pLeftNode;
	}
	else
	{
		if (pParent->pLchild == node)
		{
			pParent->pLchild = pLeftNode;
		}
		else
		{
			pParent->pRchild = pLeftNode;
		}
	}

}


//左旋
template<class T>
void BinarySearchTree<T>::leftRotate(BinaryNode<T>* node)
{

	if (NULL == node)
	{
		return;
	}

	//缓存下父节点
	BinaryNode<T>* pParent = node->pParent;
	//缓存下右子树
	BinaryNode<T>* pRight = node->pRchild;

	node->pRchild = pRight->pLchild;
	if (pRight->pLchild != NULL)
	{
		pRight->pLchild->pParent = node;
	}


	pRight->pLchild = node;
	node->pParent = pRight;

	//备注:设置父节点
	pRight->pParent = pParent;

	if (pParent == NULL)
	{
		pRoot = pRight;
	}
	else
	{
		if (pParent->pLchild == node)
		{
			pParent->pLchild = pRight;
		}
		else
		{
			pParent->pRchild = pRight;
		}
	}

}

//调整树的平衡(subRoot)
template<class T>
void BinarySearchTree<T>::AdjustTreeBalance(BinaryNode<T>* subRoot)
{
	if (NULL == subRoot)
	{
		return;
	}

	//找到最小不平衡子树
	BinaryNode<T>* pBack = subRoot;
	//当前结点的平衡因子
	int factor = 0;
	while (pBack != NULL)
	{
		//计算当前结点的平衡因子
		factor = GetBalanceFactor(pBack);
		if (abs(factor) > 1)
		{
			break;
		}

		pBack = pBack->pParent;
	}


	if (pBack == NULL)
	{
		//此时树不需要调整
		return;
	}

	if (factor > 1)
	{
		//右旋
		if (GetBalanceFactor(pBack->pLchild) > 0)
		{
			//进行一次向右旋转
			RightRotate(pBack);
		}
		else
		{
			//先把pBack->pLchild左旋一次
			leftRotate(pBack->pLchild);
			//再把pBack整体向右旋转一次
			RightRotate(pBack);
		}
	}
	else
	{
		//左旋
		if (GetBalanceFactor(pBack->pRchild) < 0)
		{
			//直接向左旋转一次
			leftRotate(pBack);
		}
		else
		{
			//先把pBack->pRcild向右旋转一次
			RightRotate(pBack->pRchild);
			//然后再把pBack整体向左旋转一次
			leftRotate(pBack);
		}
	}
}

6. 插入函数

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
//插入
template<class T>
void BinarySearchTree<T>::Insert(const T& val)
{
if (SearchNode(val))
{
cout << "节点存在,拒绝插入!" << endl;
}
//指向插入位置的父节点
BinaryNode<T>* pInsertNode = NULL;
//指向当前结点
BinaryNode<T>* pCurrent = pRoot;
while (pCurrent != NULL)
{
pInsertNode = pCurrent;
if (val < pCurrent->mValue)
{
pCurrent = pCurrent->pLchild;
}
else
{
pCurrent = pCurrent->pRchild;
}
}
//创建新节点
BinaryNode<T>* newnode = new BinaryNode<T>;
newnode->mValue = val;
newnode->pLchild = NULL;
newnode->pRchild = NULL;
newnode->pParent = pInsertNode;
//判断pInsertNode是否是NULL,如果为NULL,说明当前树是一个空树
if (pInsertNode == NULL)
{
pRoot = newnode;
}
else
{
if (val < pInsertNode->mValue)
{
pInsertNode->pLchild = newnode;
}
else
{
pInsertNode->pRchild = newnode;
}
}
++mSize;
//更新树的高度
UpdateTreeHeight(pRoot);
//调整树的平衡
AdjustTreeBalance(newnode->pParent);
}
//插入 template<class T> void BinarySearchTree<T>::Insert(const T& val) { if (SearchNode(val)) { cout << "节点存在,拒绝插入!" << endl; } //指向插入位置的父节点 BinaryNode<T>* pInsertNode = NULL; //指向当前结点 BinaryNode<T>* pCurrent = pRoot; while (pCurrent != NULL) { pInsertNode = pCurrent; if (val < pCurrent->mValue) { pCurrent = pCurrent->pLchild; } else { pCurrent = pCurrent->pRchild; } } //创建新节点 BinaryNode<T>* newnode = new BinaryNode<T>; newnode->mValue = val; newnode->pLchild = NULL; newnode->pRchild = NULL; newnode->pParent = pInsertNode; //判断pInsertNode是否是NULL,如果为NULL,说明当前树是一个空树 if (pInsertNode == NULL) { pRoot = newnode; } else { if (val < pInsertNode->mValue) { pInsertNode->pLchild = newnode; } else { pInsertNode->pRchild = newnode; } } ++mSize; //更新树的高度 UpdateTreeHeight(pRoot); //调整树的平衡 AdjustTreeBalance(newnode->pParent); }
//插入
template<class T>
void BinarySearchTree<T>::Insert(const T& val)
{
	if (SearchNode(val))
	{
		cout << "节点存在,拒绝插入!" << endl;
	}

	//指向插入位置的父节点
	BinaryNode<T>* pInsertNode = NULL;
	//指向当前结点
	BinaryNode<T>* pCurrent = pRoot;

	while (pCurrent != NULL)
	{
		pInsertNode = pCurrent;

		if (val < pCurrent->mValue)
		{
			pCurrent = pCurrent->pLchild;
		}
		else
		{
			pCurrent = pCurrent->pRchild;
		}
	}

	//创建新节点
	BinaryNode<T>* newnode = new BinaryNode<T>;
	newnode->mValue = val;
	newnode->pLchild = NULL;
	newnode->pRchild = NULL;
	newnode->pParent = pInsertNode;

	//判断pInsertNode是否是NULL,如果为NULL,说明当前树是一个空树
	if (pInsertNode == NULL)
	{
		pRoot = newnode;
	}
	else
	{
		if (val < pInsertNode->mValue)
		{
			pInsertNode->pLchild = newnode;
		}
		else
		{
			pInsertNode->pRchild = newnode;
		}
	}

	++mSize;

	//更新树的高度
	UpdateTreeHeight(pRoot);
	//调整树的平衡
	AdjustTreeBalance(newnode->pParent);
}

7. 删除函数

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
//删除算法
template<class T>
void BinarySearchTree<T>::Remove(const T& val)
{
BinaryNode<T>* pDelNode = SearchNode(val);
if (pDelNode == NULL)
{
cout << "删除的结点不存在!" << endl;
return;
}
//第一种情况,删除节点是叶子节点
if (pDelNode->pLchild == NULL && pDelNode->pRchild == NULL)
{
RemoveNoChildNode(pDelNode);
}
//第三种情况,删除节点有两个孩子
else if (pDelNode->pLchild != NULL && pDelNode->pRchild != NULL)
{
RemoveDoubleChildNode(pDelNode);
}
//第二种情况
else
{
RemoveSingleChildNode(pDelNode);
}
//释放删除节点的内存
delete pDelNode;
pDelNode = NULL;
--mSize;
}
//第一种情况,如果删除的结点是叶子节点
template<class T>
void BinarySearchTree<T>::RemoveNoChildNode(BinaryNode<T>* delNode)
{
BinaryNode<T>* pDelNode = delNode;
if (NULL == pDelNode)
{
return;
}
//判断删除的结点是否是根节点
if (pDelNode == pRoot)
{
pRoot = NULL;
}
else
{
if (pDelNode->pParent->pLchild == pDelNode)
{
pDelNode->pParent->pLchild = NULL;
}
else
{
pDelNode->pParent->pRchild = NULL;
}
}
}
//第二种情况,如果删除的结点只有一个孩子
template<class T>
void BinarySearchTree<T>::RemoveSingleChildNode(BinaryNode<T>* delNode)
{
BinaryNode<T>* pDelNode = delNode;
if (NULL == pDelNode)
{
return;
}
if (pRoot == pDelNode)
{
//拿到删除节点的子节点
BinaryNode<T>* pChild = (pRoot->pLchild == NULL ? pRoot->pRchild : pRoot->pLchild);
//设置子节点的父节点为NULL
pChild->pParent = NULL;
//pRoot指向子节点
pRoot = pChild;
}
else
{
BinaryNode<T>* pChild = (pDelNode->pLchild == NULL ? pDelNode->pRchild : pDelNode->pLchild);
//更新pChild的父节点
pChild->pParent = pDelNode->pParent;
if (pDelNode->pParent->pLchild == pDelNode)
{
pDelNode->pParent->pLchild = pChild;
}
else
{
pDelNode->pParent->pRchild = pChild;
}
}
}
//第三种情况,如果删除的结点有两个孩子
template<class T>
void BinarySearchTree<T>::RemoveDoubleChildNode(BinaryNode<T>* delNode)
{
BinaryNode<T>* pDelNode = delNode;
if (NULL == pDelNode)
{
return;
}
//删除的结点是根节点的情况
//pDelNode左子树最大值的结点,或者右子树中最小值的结点
//获得删除节点左子树中最大的结点
BinaryNode<T>* pLeftMaxNode = GetMaxNode(pDelNode->pLchild);
if (pDelNode == pRoot)
{
if (pLeftMaxNode == pDelNode->pLchild)
{
pLeftMaxNode->pRchild = pRoot->pRchild;
}
else
{
//最大值的结点的父节点指向最大值结点的左子树
pLeftMaxNode->pParent->pRchild = pLeftMaxNode->pLchild;
if (pLeftMaxNode->pLchild != NULL)
{
pLeftMaxNode->pLchild->pParent = pLeftMaxNode->pParent;
}
//让最大值结点左右指针指向根节点的左右子树
pLeftMaxNode->pLchild = pRoot->pLchild;
pLeftMaxNode->pRchild = pRoot->pRchild;
}
pRoot = pLeftMaxNode;
}
else
{
if (pLeftMaxNode == pDelNode->pLchild)
{
pLeftMaxNode->pRchild = pDelNode->pRchild;
//更新待删除结点的右子树的父节点
pDelNode->pRchild->pParent = pLeftMaxNode;
if (pDelNode->pParent->pLchild == pDelNode)
{
pDelNode->pParent->pLchild = pLeftMaxNode;
}
else
{
pDelNode->pParent->pRchild = pLeftMaxNode;
}
}
else
{
pLeftMaxNode->pParent->pRchild = pLeftMaxNode->pLchild;
if (pLeftMaxNode->pLchild != NULL)
{
pLeftMaxNode->pLchild->pParent = pLeftMaxNode->pParent;
}
pLeftMaxNode->pLchild = pDelNode->pLchild;
pLeftMaxNode->pRchild = pDelNode->pRchild;
if (pDelNode->pParent->pLchild == pDelNode)
{
pDelNode->pParent->pLchild = pLeftMaxNode;
}
else
{
pDelNode->pParent->pRchild = pLeftMaxNode;
}
}
}
}
//删除算法 template<class T> void BinarySearchTree<T>::Remove(const T& val) { BinaryNode<T>* pDelNode = SearchNode(val); if (pDelNode == NULL) { cout << "删除的结点不存在!" << endl; return; } //第一种情况,删除节点是叶子节点 if (pDelNode->pLchild == NULL && pDelNode->pRchild == NULL) { RemoveNoChildNode(pDelNode); } //第三种情况,删除节点有两个孩子 else if (pDelNode->pLchild != NULL && pDelNode->pRchild != NULL) { RemoveDoubleChildNode(pDelNode); } //第二种情况 else { RemoveSingleChildNode(pDelNode); } //释放删除节点的内存 delete pDelNode; pDelNode = NULL; --mSize; } //第一种情况,如果删除的结点是叶子节点 template<class T> void BinarySearchTree<T>::RemoveNoChildNode(BinaryNode<T>* delNode) { BinaryNode<T>* pDelNode = delNode; if (NULL == pDelNode) { return; } //判断删除的结点是否是根节点 if (pDelNode == pRoot) { pRoot = NULL; } else { if (pDelNode->pParent->pLchild == pDelNode) { pDelNode->pParent->pLchild = NULL; } else { pDelNode->pParent->pRchild = NULL; } } } //第二种情况,如果删除的结点只有一个孩子 template<class T> void BinarySearchTree<T>::RemoveSingleChildNode(BinaryNode<T>* delNode) { BinaryNode<T>* pDelNode = delNode; if (NULL == pDelNode) { return; } if (pRoot == pDelNode) { //拿到删除节点的子节点 BinaryNode<T>* pChild = (pRoot->pLchild == NULL ? pRoot->pRchild : pRoot->pLchild); //设置子节点的父节点为NULL pChild->pParent = NULL; //pRoot指向子节点 pRoot = pChild; } else { BinaryNode<T>* pChild = (pDelNode->pLchild == NULL ? pDelNode->pRchild : pDelNode->pLchild); //更新pChild的父节点 pChild->pParent = pDelNode->pParent; if (pDelNode->pParent->pLchild == pDelNode) { pDelNode->pParent->pLchild = pChild; } else { pDelNode->pParent->pRchild = pChild; } } } //第三种情况,如果删除的结点有两个孩子 template<class T> void BinarySearchTree<T>::RemoveDoubleChildNode(BinaryNode<T>* delNode) { BinaryNode<T>* pDelNode = delNode; if (NULL == pDelNode) { return; } //删除的结点是根节点的情况 //pDelNode左子树最大值的结点,或者右子树中最小值的结点 //获得删除节点左子树中最大的结点 BinaryNode<T>* pLeftMaxNode = GetMaxNode(pDelNode->pLchild); if (pDelNode == pRoot) { if (pLeftMaxNode == pDelNode->pLchild) { pLeftMaxNode->pRchild = pRoot->pRchild; } else { //最大值的结点的父节点指向最大值结点的左子树 pLeftMaxNode->pParent->pRchild = pLeftMaxNode->pLchild; if (pLeftMaxNode->pLchild != NULL) { pLeftMaxNode->pLchild->pParent = pLeftMaxNode->pParent; } //让最大值结点左右指针指向根节点的左右子树 pLeftMaxNode->pLchild = pRoot->pLchild; pLeftMaxNode->pRchild = pRoot->pRchild; } pRoot = pLeftMaxNode; } else { if (pLeftMaxNode == pDelNode->pLchild) { pLeftMaxNode->pRchild = pDelNode->pRchild; //更新待删除结点的右子树的父节点 pDelNode->pRchild->pParent = pLeftMaxNode; if (pDelNode->pParent->pLchild == pDelNode) { pDelNode->pParent->pLchild = pLeftMaxNode; } else { pDelNode->pParent->pRchild = pLeftMaxNode; } } else { pLeftMaxNode->pParent->pRchild = pLeftMaxNode->pLchild; if (pLeftMaxNode->pLchild != NULL) { pLeftMaxNode->pLchild->pParent = pLeftMaxNode->pParent; } pLeftMaxNode->pLchild = pDelNode->pLchild; pLeftMaxNode->pRchild = pDelNode->pRchild; if (pDelNode->pParent->pLchild == pDelNode) { pDelNode->pParent->pLchild = pLeftMaxNode; } else { pDelNode->pParent->pRchild = pLeftMaxNode; } } } }
//删除算法
template<class T>
void BinarySearchTree<T>::Remove(const T& val)
{
	BinaryNode<T>* pDelNode = SearchNode(val);

	if (pDelNode == NULL)
	{
		cout << "删除的结点不存在!" << endl;
		return;
	}

	//第一种情况,删除节点是叶子节点
	if (pDelNode->pLchild == NULL && pDelNode->pRchild == NULL)
	{
		RemoveNoChildNode(pDelNode);
	}
	//第三种情况,删除节点有两个孩子
	else if (pDelNode->pLchild != NULL && pDelNode->pRchild != NULL)
	{
		RemoveDoubleChildNode(pDelNode);
	}
	//第二种情况
	else
	{
		RemoveSingleChildNode(pDelNode);
	}

	//释放删除节点的内存
	delete pDelNode;
	pDelNode = NULL;
	--mSize;

}

//第一种情况,如果删除的结点是叶子节点
template<class T>
void BinarySearchTree<T>::RemoveNoChildNode(BinaryNode<T>* delNode)
{
	BinaryNode<T>* pDelNode = delNode;

	if (NULL == pDelNode)
	{
		return;
	}

	//判断删除的结点是否是根节点
	if (pDelNode == pRoot)
	{
		pRoot = NULL;
	}
	else
	{
		if (pDelNode->pParent->pLchild == pDelNode)
		{
			pDelNode->pParent->pLchild = NULL;
		}
		else
		{
			pDelNode->pParent->pRchild = NULL;
		}
	}
}

//第二种情况,如果删除的结点只有一个孩子
template<class T>
void BinarySearchTree<T>::RemoveSingleChildNode(BinaryNode<T>* delNode)
{
	BinaryNode<T>* pDelNode = delNode;

	if (NULL == pDelNode)
	{
		return;
	}

	if (pRoot == pDelNode)
	{
		//拿到删除节点的子节点
		BinaryNode<T>* pChild = (pRoot->pLchild == NULL ? pRoot->pRchild : pRoot->pLchild);
		//设置子节点的父节点为NULL
		pChild->pParent = NULL;
		//pRoot指向子节点
		pRoot = pChild;

	}
	else
	{
		BinaryNode<T>* pChild = (pDelNode->pLchild == NULL ? pDelNode->pRchild : pDelNode->pLchild);

		//更新pChild的父节点
		pChild->pParent = pDelNode->pParent;

		if (pDelNode->pParent->pLchild == pDelNode)
		{
			pDelNode->pParent->pLchild = pChild;
		}
		else
		{
			pDelNode->pParent->pRchild = pChild;
		}

	}

}
//第三种情况,如果删除的结点有两个孩子
template<class T>
void BinarySearchTree<T>::RemoveDoubleChildNode(BinaryNode<T>* delNode)
{
	BinaryNode<T>* pDelNode = delNode;

	if (NULL == pDelNode)
	{
		return;
	}

	//删除的结点是根节点的情况
	//pDelNode左子树最大值的结点,或者右子树中最小值的结点

	//获得删除节点左子树中最大的结点
	BinaryNode<T>* pLeftMaxNode = GetMaxNode(pDelNode->pLchild);
	if (pDelNode == pRoot)
	{

		if (pLeftMaxNode == pDelNode->pLchild)
		{
			pLeftMaxNode->pRchild = pRoot->pRchild;

		}
		else
		{
			//最大值的结点的父节点指向最大值结点的左子树
			pLeftMaxNode->pParent->pRchild = pLeftMaxNode->pLchild;
			if (pLeftMaxNode->pLchild != NULL)
			{
				pLeftMaxNode->pLchild->pParent = pLeftMaxNode->pParent;
			}
			//让最大值结点左右指针指向根节点的左右子树
			pLeftMaxNode->pLchild = pRoot->pLchild;
			pLeftMaxNode->pRchild = pRoot->pRchild;
		}

		pRoot = pLeftMaxNode;
	}
	else
	{

		if (pLeftMaxNode == pDelNode->pLchild)
		{
			pLeftMaxNode->pRchild = pDelNode->pRchild;
			//更新待删除结点的右子树的父节点
			pDelNode->pRchild->pParent = pLeftMaxNode;

			if (pDelNode->pParent->pLchild == pDelNode)
			{
				pDelNode->pParent->pLchild = pLeftMaxNode;
			}
			else
			{
				pDelNode->pParent->pRchild = pLeftMaxNode;
			}

		}
		else
		{
			pLeftMaxNode->pParent->pRchild = pLeftMaxNode->pLchild;
			if (pLeftMaxNode->pLchild != NULL)
			{
				pLeftMaxNode->pLchild->pParent = pLeftMaxNode->pParent;
			}

			pLeftMaxNode->pLchild = pDelNode->pLchild;
			pLeftMaxNode->pRchild = pDelNode->pRchild;

			if (pDelNode->pParent->pLchild == pDelNode)
			{
				pDelNode->pParent->pLchild = pLeftMaxNode;
			}
			else
			{
				pDelNode->pParent->pRchild = pLeftMaxNode;
			}
		}

	}
}
未经允许不得转载:一亩三分地 » 平衡二叉树实现(Balanced Binary Tree)