平衡二叉树(附自己写的源码)

平衡二叉树AVL—tree

 树中每一个节点左右孩子的高度差不超过1的有序二叉树(左右孩子的高度差)

这种也是平衡二叉树

为什么学习平衡二叉树?
先问一个问题:下面这个有序二叉树的查找效率高还是不高?

答案是不高

举个例子

        就好像担当子,要左右平衡才好担,二叉树同样如此,要左右平滑才好查找。

看如图:我们要查找最下方的1,左边和右边各要查找的次数是多少?

 

答案:左边查找1,找6次,右边查找1,找4次

所以要查找效率高一点,就希望是右边这种树

所以有了新的概念,高度:距离根节点有多少层

(查找数据的高度)如:根为1,根孩子:2,根孩子的孩子:3

那么如何做出平衡二叉树?旋转!

  1. 有序二叉树方式插入节点
  2. 判断是否平衡(左右高度差是否超过1)

                        如果平衡   设置高度

                        如果不平衡 用旋转(不平衡变平衡) 设置高度

不平衡的四种情况:

 

判断是那种情况导致的不平衡,在针对这种情况

第一种:以当前节点的父节点(11)右旋

第二种:以当前节点的父节点(11)左旋

第三种:(左右旋)先以当前节点(10)左旋,然后以当前节点的父节点(11)为轴右旋

 

第四种:(右左旋)先以当前节点(10)左旋,然后以当前节点的父节点(11)为轴右旋

 

右旋原理

 

左旋原理

代码:

头文件:

#pragma once
#include <iostream>
using namespace std;
//节点类型
template<class T>
struct treeNode 
{
	T			data;		//数据
	treeNode*	pLeft;		//左孩子
	treeNode*	pRight;		//右孩子
	int			height;		//高度

	treeNode(const T& data)
	{
		this->data = data;
		pLeft = pRight = NULL;
		height = 0;
	}
};



template<class T>
class myAVLtree
{
public:
	treeNode<T>* pRoot;//指向根节点的指针

public:
	myAVLtree() { pRoot = NULL; }
	~myAVLtree(){}

	void insertNode(const T& data);
	

private:
	void _insertNode(treeNode<T>*& root, const T& data);
	//获取某节点高度
	int _getNodeHeight(treeNode<T>* root);
	//旋转的代码要是以谁为轴,所以单独写
	//右旋
	treeNode<T>* rightRotator(treeNode<T>* root);
	//左旋
	treeNode<T>* leftRotator(treeNode<T>* root);
	//左右旋
	treeNode<T>* LRRotator(treeNode<T>* root);
	//右左旋
	treeNode<T>* RLRotator(treeNode<T>* root);
};

//public 函数
template<class T>
void myAVLtree<T>::insertNode(const T& data)
{
	_insertNode(pRoot, data);
}



//private 函数
//添加函数
template<class T>
void myAVLtree<T>::_insertNode(treeNode<T>*& root, const T& data)
{
	//先用有序二叉树的插入
	if (root==NULL)
	{
		root = new treeNode<T>(data);
	}
	else if (data<root->data)//左子树进行插入
	{
		_insertNode(root->pLeft,data);
		//判断是否平衡
		if ((_getNodeHeight(root->pLeft) - _getNodeHeight(root->pRight))>1)
		{
			//这就只有1,3两种情况
			if (data<root->pLeft->data)//情况一 需要右旋
			{
				root=rightRotator(root);
			}
			else//情况三 需要左右旋
			{
				root=LRRotator(root);
			}
		}
	}
	else//右子树进行插入
	{
		_insertNode(root->pRight, data);
		//判断是否平衡
		if ((_getNodeHeight(root->pRight) - _getNodeHeight(root->pLeft)) > 1)
		{
			//这就只有2,4两种情况
			if (data >= root->pRight->data)//情况二 需要左旋
			{
				root=leftRotator(root);
			}
			else//情况四 需要右左旋
			{
				root=RLRotator(root);
			}
		}
	}
	//上面旋转完之后要记得设置高度,高度是会变的
	int leftHeight=_getNodeHeight(root->pLeft);
	int rightHeight = _getNodeHeight(root->pRight);
	root->height = 1 + ((leftHeight > rightHeight) ? leftHeight : rightHeight);

}

//获取某节点高度
template<class T>
int myAVLtree<T>::_getNodeHeight(treeNode<T>* root)
{
	if (root)
	{
		return root->height;
	}
	return 0;
}
//右旋
template<class T>
treeNode<T>* myAVLtree<T>::rightRotator(treeNode<T>* root)
{
	//1.pTemp存储
	treeNode<T>* pTemp = root->pLeft;
	//2.让temp的右孩子成为root的左孩子
	root->pLeft = pTemp->pRight;
	//3.root成为temp的右孩子
	pTemp->pRight= root;
	//4.设置高度
	root->height = 1 + ((_getNodeHeight(root->pLeft) > _getNodeHeight(root->pRight))?
						_getNodeHeight(root->pLeft): _getNodeHeight(root->pRight));
	//temp的高度也要变
	pTemp->height = 1 + ((_getNodeHeight(pTemp->pLeft) > _getNodeHeight(pTemp->pRight)) ?
						_getNodeHeight(pTemp->pLeft) : _getNodeHeight(pTemp->pRight));
	//5.return temp
	return pTemp;


}
//左旋
template<class T>
treeNode<T>* myAVLtree<T>::leftRotator(treeNode<T>* root)
{
	//1.pTemp存储
	treeNode<T>* pTemp = root->pRight;
	//2.让temp的左孩子成为root的右孩子
	root->pRight = pTemp->pLeft;
	//3.root成为temp的左孩子
	pTemp->pLeft = root;
	//4.设置高度
	root->height = 1 + ((_getNodeHeight(root->pLeft) > _getNodeHeight(root->pRight)) ?
		_getNodeHeight(root->pLeft) : _getNodeHeight(root->pRight));
	//temp的高度也要变
	pTemp->height = 1 + ((_getNodeHeight(pTemp->pLeft) > _getNodeHeight(pTemp->pRight)) ?
		_getNodeHeight(pTemp->pLeft) : _getNodeHeight(pTemp->pRight));
	//5.return temp
	return pTemp;
}
//左右旋
template<class T>
treeNode<T>* myAVLtree<T>::LRRotator(treeNode<T>* root)
{
	//以root的左孩子为轴左旋
	root->pLeft = leftRotator(root->pLeft);
	//以root为轴右旋
	return rightRotator(root);
}
//右左旋
template<class T>
treeNode<T>* myAVLtree<T>::RLRotator(treeNode<T>* root)
{
	//以root的右孩子为轴右旋
	root->pRight = rightRotator(root->pRight);
	//以root为轴左旋
	return leftRotator(root);
}

源文件:

#include "AVL_tree.h"
int main()
{
	int arr[10] = { 11,66,55,77,88,12,33,46,84,13 };
	myAVLtree<int> tree;
	for (int i = 0; i < 10; i++)
	{
		tree.insertNode(arr[i]);
	}
	while (1)
	{

	}
	return 0;
}

Status InsertBST(BSTree &T,ElemType e); //实现树的节点的插入 Status PreOrderTraverse(BSTree T); //实现树的递归前序遍历 Status InOrderTraverse(BSTree T); //实现树的递归中序遍历 Status PostOrderTraverse(BSTree T); //实现树的递归后序遍历 Status AllOrderTraverse(BSTree T); //实现三种递归遍历的打印 Status NonPreOrder(BSTree T,Stack S); //实现树的非递归前序遍历 Status NonInOder(BSTree T,Stack S); //实现树的非递归中序遍历 Status NonPostOrder(BSTree T,Stack S); //实现树的非递归后序遍历 Status NonAllOrder(BSTree T,Stack S); //实现三种非递归遍历的打印 Status LevelTraverse(BSTree T,Queue Q); //实现二叉树的层次遍历 Status PostsSearch(BSTree T,ElemType e);//实现二叉树中给定关键字的查找 Status SwapSubtree(BSTree T); //实现结点左右子树的交换 int TreeDepth(BSTree T); //实现二叉树深度的求值 int TotalNodeNum(BSTree T); //实现二叉树总结点数的求值 int LeafNodeNum(BSTree T); //实现二叉树叶子结点数的求值 Status DeleteBST(BSTree &T,ElemType e); //实现树的节点的删除 int TreeHeight(BSTree T); //实现树的高度的求值 int Max(int a,int b); //实现两个数中求最大值 Position MinElemSearch(BSTree T); //实现最小元素的查找 BSTree LeftRotate(BSTree g); //实现二叉树一次右旋转操作 BSTree RightRotate(BSTree g); //实现二叉树一次左旋转操作 BSTree L_RRotate(BSTree g); //实现一次先左旋转再右旋转操作 BSTree R_LRotate(BSTree g); //实现一次先右旋转再左旋转操作 Status CreatStack(Stack &S); //实现栈的建立 Status CreatQueue(Queue &Q); //实现队列的建立
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

多方通行8

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值