【数据结构】快速实现平衡二叉树(可观察每一次插入后的结果)

为了算法考试需要,我在实验室苦熬了一晚上,终于从零开始学会了平衡二叉树,不过只有二叉树的插入,没有删除操作,以后如果有时间就补上。最后会附上完整代码,我在里面写了一段输出函数,顺便会给大家两组测试数据,可以观察平衡二叉树每一次插入的运行结果呦,我尽量让它看起来对称,不过数值的位数不同就没办法了,所以各位凑合着看吧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型
LL型变换

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型变换
然后是复杂的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

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值