平衡二叉树
/*
平衡二叉树:
概念:(树中每个节点)左右子树高度差不超过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;
}