为了算法考试需要,我在实验室苦熬了一晚上,终于从零开始学会了平衡二叉树,不过只有二叉树的插入,没有删除操作,以后如果有时间就补上。最后会附上完整代码,我在里面写了一段输出函数,顺便会给大家两组测试数据,可以观察平衡二叉树每一次插入的运行结果呦,我尽量让它看起来对称,不过数值的位数不同就没办法了,所以各位凑合着看吧OwO
struct node{
int data;
int height;
node *lc;
node *rc;
node(int x):data(x),height(0),lc(NULL),rc(NULL){}
};
这是二叉树的结构体定义,包括数据,深度,左右子树和初始化。
平衡二叉树的两个重点:
1.计算平衡因子(深度)
2.旋转二叉树
比较两边子树的深度,返回最大的加一即可(如果子树为空返回-1),平衡因子名字比较拗口不好记,建议初学者(比如我)就直接用深度来记忆,任意一个点左右子树深度差大于2就不平衡了,需要旋转。
平衡因子为2:代表左边子树比右边子树深2个
平衡因子为-2:代表右边子树比左边子树深2个
旋转分为四种:
1.LL型(根节点的平衡因子为2,根节点的左子树的平衡因子为1)
2.LR型(根节点的平衡因子为2,根节点的左子树的平衡因子为-1)
2.RR型(根节点的平衡因子为-2,根节点的左子树的平衡因子为-1)
2.RL型(根节点的平衡因子为-2,根节点的左子树的平衡因子为1)
是不是这样就可以理解什么时候需要用什么旋转了?
那么旋转是怎么实现的呢?
LL型和RR型对称,LR型与RL型对称,所以我就介绍一下LL型和LR型
void LL(node* &root){
node *a;
a=root->lc;//将A的左子树B赋给a
root->lc=a->rc;//将BL扔给A作为左子树(因为B<BR<A)
a->rc=root;//将A作为B的右子树(B<A)
a->height=max(GetHeight(a->lc),GetHeight(a->rc))+1;//更新B的深度
root->height=max(GetHeight(root->lc),GetHeight(root->rc))+1;//更新A的深度
root=a; //根节点指向B,旋转完成
}
结合图片和注释和代码,应该能很快看懂的
void RR(node* &root){//RR也贴上,不过不写注释了
node *a;
a=root->rc;
root->rc=a->lc;
a->lc=root;
a->height=max(GetHeight(a->lc),GetHeight(a->rc))+1;
root->height=max(GetHeight(root->lc),GetHeight(root->rc))+1;
root=a;
}
然后是复杂的LR型,是不是很烦?不过它的代码超短的!
void LR(node* &root){
RR(root->lc);
LL(root);
}
惊不惊喜,意不意外?结合前面的两种旋转画画图理解一下就行
最后附上源代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
int N;
int p[10][1024];
struct node{
int data;
int height;
node *lc;
node *rc;
node(int x):data(x),height(0),lc(NULL),rc(NULL){}
};
int GetHeight(node* &a){
if(a==NULL) return -1;
else return a->height;
}
void LL(node* &root){
node *a;
a=root->lc;
root->lc=a->rc;
a->rc=root;
a->height=max(GetHeight(a->lc),GetHeight(a->rc))+1;
root->height=max(GetHeight(root->lc),GetHeight(root->rc))+1;
root=a;
}
void RR(node* &root){
node *a;
a=root->rc;
root->rc=a->lc;
a->lc=root;
a->height=max(GetHeight(a->lc),GetHeight(a->rc))+1;
root->height=max(GetHeight(root->lc),GetHeight(root->rc))+1;
root=a;
}
void LR(node* &root){
RR(root->lc);
LL(root);
}
void RL(node* &root){
LL(root->rc);
RR(root);
}
void print(node* &root,int h,int temp,int H){//为打印数组赋值
if(root->lc!=NULL)
p[H-h+1][temp-(int)pow(2,h-1)]=root->lc->data,print(root->lc,h-1,temp-(int)pow(2,h-1),H);
if(root->rc!=NULL)
p[H-h+1][temp+(int)pow(2,h-1)]=root->rc->data,print(root->rc,h-1,temp+(int)pow(2,h-1),H);
}
void Print(node* &root){//打印
memset(p,0,sizeof(p));
int h=root->height;
p[0][(int)pow(2,h)-1]=root->data;
print(root,h,(int)pow(2,h)-1,h);
for(int i=0;i<=root->height+1;i++){
for(int j=0;j<(int)pow(2,h+1);j++){
if(p[i][j])printf("%d",p[i][j]);
else printf(" ");
}
printf("\n\n");
}
}
void Insert(node* &root,int val){
if(root==NULL){
root=new node(val);
return ;
}
if(val<root->data){//插入左子树
Insert(root->lc,val);
if(GetHeight(root->lc)-GetHeight(root->rc)>1){//发现不平衡
if(val<root->lc->data) LL(root);//判断是否为LL型
else LR(root);//否则为LR型
}
}
if(val>root->data){//插入右子树
Insert(root->rc,val);
if(GetHeight(root->rc)-GetHeight(root->lc)>1){//发现不平衡
if(val>root->rc->data) RR(root);//判断是否为RR型
else RL(root);//否则为RL型
}
}
root->height = max(GetHeight(root->lc), GetHeight(root->rc)) + 1;
}
int main() {
scanf("%d",&N);
int a;
node *root=NULL;
for(int i=0;i<N;i++){
scanf("%d",&a);
Insert(root,a);
Print(root);
}
exit(0);
}
测试数据:
Sample Input 1:
5
88 70 61 63 65
Sample Input 2:
8
88 70 61 96 120 90 65 68