AVL平衡二叉树

定义

  • 单个节点是AVL树
  • 左右子树高差差不大于1
  • 左右子树都是AVL树

平衡因子

  • 左子树高度减去右子树高度
  • 如果平衡因子绝对值超过1,就必须调整。

调整类型

  • 找到引起失衡的节点
  • 计算平衡因子

右右型

  • 平衡因子为负则是右X型
  • 失衡结点右孩子的平衡因子为负则是右右型
  • 调整方法是整体左旋,与左左型调整类似

左左型

  • 失衡结点的平衡因子为正则是左X型
  • 失衡结点左孩子的平衡因子为正则是左左型
  • 调整方法是整体右旋,失衡点左孩子的右孩子改挂到右结点
失衡
插入
R
  • 调整后
插入
失衡
R

右左型

  • 平衡因子为负则是右X型
  • 因插入左孩子引起结点的失衡,则为右左型
  • 调整方法,先右旋再左旋

左右型

  • 平衡因子为负则是右X型
  • 因插入右孩子引起结点的失衡,则为右左型
  • 失衡节点的右孩子的平衡因子为负
  • 调整方法,先右旋再左旋
3
1
C
D
2
L
R
  • 调整后 先局部左旋,再整体右旋
2
1
3
D
L
R
C

代码

#include <iostream>
#include <cmath>
using namespace std;
struct AVLTree{
	int data;
	AVLTree * left;
	AVLTree * right; 
	AVLTree(int x){
		data = x;
		left=right=NULL;
	}
	AVLTree * add(AVLTree *p){
		if(p->data < data)
			left=left?left->add(p):p;
		else
			right=right?right->add(p):p;
		return adj();
	}
	void in_order(){
		if(left) left->in_order();
		cout<<data<<" ";
		if(right) right->in_order();
	}
	int h(){
		int a=left?left->h():0;
		int b=right?right->h():0;
		return max(a,b)+1;
	}
	int balance(){
		int a=left?left->h():0;
		int b=right?right->h():0; 
		return a-b;
	}
	AVLTree * adj(){
		if(abs(balance())<2) return this;
		if(balance()>0){
			if(left->balance()>0){
				AVLTree * r=left;
				left=r->right;
				r->right=this;
				return r;
			}
			else{
				AVLTree * r=left->right;
				left->right=r->left;
				r->left=left;
				left=r->right;
				r->right=this;
				return r;
			}
		}
		else{
			if(right->balance()<0){
				AVLTree * r=right;
				right=r->left;
				r->left=this;
				return r;
			}
			else{
				AVLTree* r=right->left;
				right->left=r->right;
				r->right=right;
				right=r->left;
				r->left=this;
				return r;
			}
			}
	}
}; 

int main(){
	int data[]={10,8,9,6,7,5,4,3,2,1};
	AVLTree * r=new AVLTree(data[0]);
	for(int i=1;i<sizeof(data)/sizeof(int);++i)
		r=r->add(new AVLTree(data[i]));
	r->in_order();
	cout<<endl;
	cout<<r->h()<<endl;
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值