所谓平衡二叉树是指树中任一结点的左、右子树高度大致相同。 平衡二叉树有很多种最著名的是由前苏联数学家Adelse—Velskil和Landis在1962年提出的,称为AVL树。平衡二叉树(AVL树)定义如下: 平衡二叉树或者是一棵空树,或者是具有以下性质的二叉排序树: (1)它的左子树和右子树的高度之差绝对值不超过1; (2)它的左子树和右子树都是平衡二叉树。
通过以上几种性质 我们低昂以一个这样的二叉树
可以看出 这不是一个平衡二叉树
40这个节点的节点最大高度差为2
那么我们会用到旋转的方法让他变成一个平衡二叉树
这里我们主要介绍右旋
可以看出 我们的二叉树是这样一个结构 A为不平衡节点
一般的 我们将
不平衡节点的父亲
不平衡节点
不平衡节点的左
不平衡节点的左的右
四个节点进行操作来完成右旋
对节点的孩子关系的操作
A->左=B->右(E)
B->右=A
x->左(或右)=B
对节点的父亲的操作
E->父亲=A
A->父亲=B
B->父亲=x
通过右旋转将左边的二叉树变成右边的平衡二叉树
下面是右旋函数 传根的引用
void RightRotate(BinaryTree*& pBoot)
{
if (pBoot == nullptr || pBoot->pLeft==nullptr)
{
return;
}
//标记不平衡节点 A
BinaryTree* pMark = pBoot;
//标记不平衡节点的左 B
BinaryTree* pTemp = pBoot->pLeft;
//x pMark->pFather E pTemp->pRight
//三个孩子
//不平衡节点的左->不平衡节点的 左的右 A->左=E
pMark->pLeft = pTemp->pRight;
//不平衡节点左的右->不平衡节点 B->右=A
pTemp->pRight = pMark;
//不平衡节点是不是根
//是 不平衡的节点变为根
if (pMark->pFather == nullptr)
{
pBoot=pTemp;
}
//不是 判断不平衡节点是父亲的左还是右 (A是父亲的左还是右)
else
{
//左:
//不平衡节点的父亲的左孩子->不平衡节点 X->左=B
if (pMark->pFather->pLeft == pMark)
{
pMark->pFather->pLeft =pTemp;
}
//右:
//不平衡节点的父亲的右孩子->不平衡节点 X->右=B
else
{
pMark->pFather->pRight = pTemp;
}
}
//三个父亲
//不平衡节点左的右的父亲->不平衡节点 E->父亲=A
if (pMark->pLeft!=nullptr)
{
pMark->pLeft->pFather = pMark;
}
//不平衡节点的左(B)的父亲=不平衡节点(A)的父亲
pTemp->pFather = pMark->pFather;
//不平衡节点(A)的父亲=不平衡节点的左(B)
pMark->pFather = pTemp;
}
在主函数中我们定义一个这样的二叉树
//根
BinaryTree* pBoot = new BinaryTree;
pBoot->pFather = nullptr;
pBoot->id = 40;
//左
pBoot->pLeft = new BinaryTree;
pBoot->pLeft->id = 20;
pBoot->pLeft->pFather = pBoot;
//左的左
pBoot->pLeft->pLeft = new BinaryTree;
pBoot->pLeft->pLeft->id = 10;
pBoot->pLeft->pLeft->pFather = pBoot->pLeft;
//左的左的左
pBoot->pLeft->pLeft->pLeft = new BinaryTree;
pBoot->pLeft->pLeft->pLeft->id = 7;
pBoot->pLeft->pLeft->pLeft->pFather = pBoot->pLeft->pLeft;
pBoot->pLeft->pLeft->pLeft->pLeft = NULL;
pBoot->pLeft->pLeft->pLeft->pRight = NULL;
//左的左的右
pBoot->pLeft->pLeft->pRight = NULL;
//左的右
pBoot->pLeft->pRight = new BinaryTree;
pBoot->pLeft->pRight->id = 30;
pBoot->pLeft->pRight->pFather = pBoot->pLeft;
pBoot->pLeft->pRight->pLeft = NULL;
pBoot->pLeft->pRight->pRight = NULL;
//右
pBoot->pRight = new BinaryTree;
pBoot->pRight->id = 50;
pBoot->pRight->pFather = pBoot;
pBoot->pRight->pLeft = NULL;
pBoot->pRight->pRight = NULL;
然后对其根节点40进行右旋 使其变为平衡二叉树
RightRotate(pBoot);
完整代码如下
#include<iostream>
#include<stack>
using namespace std;
//二叉排序树中不允许出现相同的值的节点
struct BinaryTree
{
int id;
BinaryTree* pLeft;
BinaryTree* pRight;
BinaryTree* pFather;
};
void Inorder(BinaryTree *pBoot)
{
if (pBoot == nullptr)
{
return;
}
Inorder(pBoot->pLeft);
cout << pBoot->id << " ";
Inorder(pBoot->pRight);
}
void RightRotate(BinaryTree*& pBoot)
{
if (pBoot == nullptr || pBoot->pLeft==nullptr)
{
return;
}
//标记不平衡节点 A
BinaryTree* pMark = pBoot;
//标记不平衡节点的左 B
BinaryTree* pTemp = pBoot->pLeft;
//x pMark->pFather E pTemp->pRight
//三个孩子
//不平衡节点的左->不平衡节点的 左的右 A->左=E
pMark->pLeft = pTemp->pRight;
//不平衡节点左的右->不平衡节点 B->右=A
pTemp->pRight = pMark;
//不平衡节点是不是根
//是 不平衡的节点变为根
if (pMark->pFather == nullptr)
{
pBoot=pTemp;
}
//不是 判断不平衡节点是父亲的左还是右 (A是父亲的左还是右)
else
{
//左:
//不平衡节点的父亲的左孩子->不平衡节点 X->左=B
if (pMark->pFather->pLeft == pMark)
{
pMark->pFather->pLeft =pTemp;
}
//右:
//不平衡节点的父亲的右孩子->不平衡节点 X->右=B
else
{
pMark->pFather->pRight = pTemp;
}
}
//三个父亲
//不平衡节点左的右的父亲->不平衡节点 E->父亲=A
if (pMark->pLeft!=nullptr)
{
pMark->pLeft->pFather = pMark;
}
pTemp->pFather = pMark->pFather;
pMark->pFather = pTemp;
}
int main()
{
//根
BinaryTree* pBoot = new BinaryTree;
pBoot->pFather = nullptr;
pBoot->id = 40;
//左
pBoot->pLeft = new BinaryTree;
pBoot->pLeft->id = 20;
pBoot->pLeft->pFather = pBoot;
//左的左
pBoot->pLeft->pLeft = new BinaryTree;
pBoot->pLeft->pLeft->id = 10;
pBoot->pLeft->pLeft->pFather = pBoot->pLeft;
//左的左的左
pBoot->pLeft->pLeft->pLeft = new BinaryTree;
pBoot->pLeft->pLeft->pLeft->id = 7;
pBoot->pLeft->pLeft->pLeft->pFather = pBoot->pLeft->pLeft;
pBoot->pLeft->pLeft->pLeft->pLeft = NULL;
pBoot->pLeft->pLeft->pLeft->pRight = NULL;
//左的左的右
pBoot->pLeft->pLeft->pRight = NULL;
//左的右
pBoot->pLeft->pRight = new BinaryTree;
pBoot->pLeft->pRight->id = 30;
pBoot->pLeft->pRight->pFather = pBoot->pLeft;
pBoot->pLeft->pRight->pLeft = NULL;
pBoot->pLeft->pRight->pRight = NULL;
//右
pBoot->pRight = new BinaryTree;
pBoot->pRight->id = 50;
pBoot->pRight->pFather = pBoot;
pBoot->pRight->pLeft = NULL;
pBoot->pRight->pRight = NULL;
Inorder(pBoot);
RightRotate(pBoot);
cout << endl;
Inorder(pBoot);
return 0;
}