数据结构学习第二十一课(平衡二叉树)

平衡二叉树

/*
平衡二叉树:
概念:(树中每个节点)左右子树高度差不超过1的有序二叉树;
每个节点都先按照有序二叉树的方式来插入:
如果不平衡:有四种情况
先判断是哪种不平衡的情况,新结点是当前节点的左孩子还是右孩子

新节点:pNew
当前节点:pCurrent
根结点:pRoot
if(pCurrent==pRoot->pLeft)//当前节点是根结点
{
if(pNew==pCurrent->pLeft)//新节点是当前节点左孩子
{
RR();//右旋
}
else//新节点是当前节点的右孩子
{
LR();//左右旋
}
}
else//当前节点是根结点的右孩子
{
if(pNew==pCurrent->pLeft)//新节点是当前节点的左孩子
{
RL();//右左旋
}
else//新节点是当前节点的右孩子
{
LL();//左旋
}

}

*/

1,头文件

#pragma once

// 左 < 根 < 右

//平衡二叉树节点类型
template<class T>
struct TreeNode{
	T			data;	//数据
	TreeNode*	pLeft;	//左孩子
	TreeNode*	pRight;	//右孩子
	int			height;	//高度

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

template<class T>
class AVLTree{
	TreeNode<T>*		pRoot;	//指向根节点
public:
	AVLTree(){ pRoot = NULL; }	//构造器
	~AVLTree(){}				//析构器 暂不实现  参考有序二叉树

	void insert(const T& data);	//往平衡二叉树中插入一个节点
private:
	void _insertNodeToTree(TreeNode<T>*& root, const T& data);//内部调用的插入节点函数
	int _getHeight(TreeNode<T>* root);//获取树的高度

	//左旋  对应 情况 一
	TreeNode<T>* LL(TreeNode<T>* root);
	//右旋  对应 情况 二
	TreeNode<T>* RR(TreeNode<T>* root);
	//右左旋  对应 情况 三
	TreeNode<T>* RL(TreeNode<T>* root);
	//左右旋  对应 情况 四
	TreeNode<T>* LR(TreeNode<T>* root);
};
template<class T>
//往平衡二叉树中插入一个节点
void AVLTree<T>::insert(const T& data){
	_insertNodeToTree(pRoot, data);
}

template<class T>
//内部调用的插入节点函数
void AVLTree<T>::_insertNodeToTree(TreeNode<T>*& root, const T& data){
	//1 如果root为NULL
	if (NULL == root){
		root = new TreeNode<T>(data);//新节点成为根节点
	}
	//2 如果root不为NULL
	else if(data > root->data){//新节点比当前节点大  往右边插入
		_insertNodeToTree(root->pRight, data);
		//检查是否需要旋转
		if ( (_getHeight(root->pRight) - _getHeight(root->pLeft) ) > 1){
			if (data > root->pRight->data){//需要左旋 情况一
				printf("左旋\n");
				root = LL(root);
			}
			else{//需要右左旋 情况三
				printf("右左旋\n");
				root = RL(root);
			}
		}
	}
	else{//新节点比当前节点小  往左边插入
		_insertNodeToTree(root->pLeft, data);
		//检查是否需要旋转
		if ((_getHeight(root->pLeft) - _getHeight(root->pRight)) > 1){
			if (data < root->pLeft->data){//需要右旋 情况二
				printf("右旋\n");
				root = RR(root);
			}
			else{//需要左右旋 情况四
				printf("左右旋\n");
				root = LR(root);
			}
		}
	}
	//3 设置高度
	int lh, rh;
	lh = _getHeight(root->pLeft);
	rh = _getHeight(root->pRight);

	root->height = 1 + ( (lh > rh) ? lh : rh );
}

template<class T>
//获取树的高度
int AVLTree<T>::_getHeight(TreeNode<T>* root){
#if 0
	if (NULL == root) return 0;
	else return root->height;
#else
	if (root) return root->height;
	return 0;
#endif
}

template<class T>
//左旋  对应 情况 一
TreeNode<T>* AVLTree<T>::LL(TreeNode<T>* root){
	//1 pTemp临时记录root的右孩子
	TreeNode<T>* pTemp = root->pRight;
	//2 pTemp的左孩子成为root的右孩子
	root->pRight = pTemp->pLeft;
	//3 root成为pTemp的左孩子
	pTemp->pLeft = root;
	//4 重新设置高度
	//4.1 重新计算root的高度
	root->height = 1 +
		((_getHeight(root->pLeft) > _getHeight(root->pRight)) ? 
		_getHeight(root->pLeft) : _getHeight(root->pRight));
	//4.2 重新计算pTemp的高度
	pTemp->height = 1 +
		((_getHeight(pTemp->pLeft) > _getHeight(pTemp->pRight)) ?
		_getHeight(pTemp->pLeft) : _getHeight(pTemp->pRight));
	//5 返回pTemp(改变根节点)
	return pTemp;
}

template<class T>
//右旋  对应 情况 二
TreeNode<T>* AVLTree<T>::RR(TreeNode<T>* root){
	//1 pTemp记录root的左孩子
	TreeNode<T>* pTemp = root->pLeft;
	//2 pTemp的右孩子成为root的左孩子
	root->pLeft = pTemp->pRight;
	//3 root成为pTemp的右孩子
	pTemp->pRight = root;
	//4 重新设置高度
	//4.1 重新计算root的高度
	root->height = 1 +
		((_getHeight(root->pLeft) > _getHeight(root->pRight)) ?
		_getHeight(root->pLeft) : _getHeight(root->pRight));
	//4.2 重新计算pTemp的高度
	pTemp->height = 1 +
		((_getHeight(pTemp->pLeft) > _getHeight(pTemp->pRight)) ?
		_getHeight(pTemp->pLeft) : _getHeight(pTemp->pRight));
	//5 返回pTemp(改变根节点)
	return pTemp;
}

template<class T>
//右左旋  对应 情况 三
TreeNode<T>* AVLTree<T>::RL(TreeNode<T>* root){
	//以root的right为轴右旋
	root->pRight = RR(root->pRight);
	//以root为轴左旋
	return LL(root);
}

template<class T>
//左右旋  对应 情况 四
TreeNode<T>* AVLTree<T>::LR(TreeNode<T>* root){
	root->pLeft = LL(root->pLeft);//以root的left为轴左旋
	//以root为轴右旋
	return RR(root);
}

2,源文件

#include<stdio.h>
#include"AVLTree2.h"
int main()
{
	AVLTree<int> tree;
	tree.insert(99);
	tree.insert(66);
	tree.insert(33);
	tree.insert(56);
	tree.insert(25);
	tree.insert(32);
	tree.insert(89);
	tree.insert(87);
	tree.insert(12);
	tree.insert(16);
	tree.insert(79);
	tree.insert(65);	
	while (1);
	return 0;
}
上一篇:快速排序


下一篇:反弹shell及其脚本