PAT A1066 Root of AVL Tree

PAT A1066 Root of AVL Tree

在这里插入图片描述在这里插入图片描述

Sample Input 1:

5
88 70 61 96 120

Sample Output 1:

70

Sample Input 2:

7
88 70 61 96 120 90 65

Sample Output 2:

88
  • 思路 1:
    一、模拟AVL树的建立:
  1. create():将输入序列依次insert()到树上
  2. insert():再BST得基础上,还要保证|平衡因子| < 2,所以我们还需要一个 getBalanceFactor(),一但插入使某一节点得平衡因子达到2,就需要调整,调整需要:左旋L()和右旋R()
  3. getBalanceFactor():每个结点得平衡因子都为其左子树高度 - 右,所有我们需要每次插入时实时更新高度updateHeight()
  4. updateHeight():每个结点得高度,就是其左右子树高度最大值+1,所有还需要一个getHeight(),以及每个结点中应存有记录高度的变量height
create
insert
getBalanceFactor
L / R
updateHeight
getHeight

二、调整方式:
如题所示,插入破坏平衡的情况可以分为4种:LL, LR, RR, RL(当前结点root 的左孩子的左子树上插入 / 左孩子的右子树插入 / …)

LL: 对root右旋(往左边偏,向右边掰直; RR: 对root左旋
LR: 先对root-lchild右旋,即可转化为LL; RL: 同理root->rchild左旋->RR

三、左右旋:
L():左旋(一定是向右偏)
在这里插入图片描述
按元素从小到大排列为:aL < (a) < bL < b < bR
所以上树,等价于:aL < a < bL < (b) < bR
在这里插入图片描述
从上面两图可以看到,bL上插入一个结点,会导致a失衡,而通过一次左旋,恰好将其抵消掉了(且左旋后的树等价于旋转前)

变化有:
bL: (b->rc) --> (a->lc)
b:(root->rc) --> (root)
a:(root) --> (b->lc)
=》设置一个临时指针指向b:

1) root->rc = tmp->lc;

2) tmp->lc = root;

3) tmp = root;

(!!!:别忘了更新变化过的结点(a和b)的高度变化!!!)

  • TIPS 1:

1) L/R 、2) insert都需要加&,需要改变root的原值

  • code 1:
#include <iostream>
using namespace std;
const int maxn = 110;
int n, input[maxn];
struct node{
	int data, height;
	node *lc, *rc;
};
node* newNode(int x){
	node* n = new node;
	n->data = x;
	n->height = 1;
	n->lc = n->rc = NULL;
	return n;
}
int getHeight(node* root){
	if(root == NULL) return 0;
	return root->height;	
}
int updateHeight(node* root){
	root->height = max(getHeight(root->lc), getHeight(root->rc)) + 1;
}
int getBalanceFactor(node* root){
	return getHeight(root->lc) - getHeight(root->rc);
}
void L(node* &root){
	node * tmp = root->rc;
	root->rc = tmp->lc;
	tmp->lc = root;
	updateHeight(root);
	updateHeight(tmp);
	root = tmp;
}
void R(node* &root){
	node * tmp = root->lc;
	root->lc = tmp->rc;
	tmp->rc = root;
	updateHeight(root);
	updateHeight(tmp);
	root = tmp;
}
void insert(node* &root, int x){
	if(root == NULL){
		root = newNode(x);
		return;
	}
	if(x < root->data){
		insert(root->lc, x);
		updateHeight(root);
		if(getBalanceFactor(root) == 2){	//L型 
			if(getBalanceFactor(root->lc) == 1){	//LL型 
				R(root);
			}else if(getBalanceFactor(root->lc) == -1){	//LR型 
				L(root->lc);
				R(root);
			}
		}
		
	}else{
		insert(root->rc, x);
		updateHeight(root);
		if(getBalanceFactor(root) == -2){	//R型 
			if(getBalanceFactor(root->rc) == -1){	//RR型 
				L(root);
			}else if(getBalanceFactor(root->rc) == 1){	//RL型 
				R(root->rc);
				L(root);
			}
		}
	}
}
node* create(){
	node* root = NULL;
	for(int i = 0; i < n; ++i){
		insert(root, input[i]);
	}
	return root;
}
int main(){
	scanf("%d", &n);
	for(int i = 0; i < n; ++i)
		scanf("%d", &input[i]);
	node* r = create();
	printf("%d", r->data);
	return 0;
} 
  • 思路 2:静态树实现版
  • code 2:
#include <iostream>
using namespace std;
const int maxn = 110;
int n, input[maxn], idex = 0;
struct Node{
	int data, height, lc, rc;
}node[maxn];
int newNode(int x){
	idex++;
	node[idex].data = x;
	node[idex].lc = node[idex].rc = -1;
	node[idex].height = 1;
	return idex;
}
int getHeight(int root){
	if(root == -1) return 0;
	return node[root].height;
}
void updateHeight(int root){
	node[root].height = max(node[node[root].lc].height, node[node[root].rc].height) + 1;
}
int getBalanceFactor(int root){
	//return node[node[root].lc].h - node[node[root].rc].h;		//Wrong 1:
	return getHeight(node[root].lc) - getHeight(node[root].rc); 	
}
void L(int &root){
	int tmp = node[root].rc;
	///node[root].rc = tmp;	 	//Wrong 2: 
	node[root].rc = node[tmp].lc;	
	node[tmp].lc = root;
	updateHeight(root);
	updateHeight(tmp);
	root = tmp;
}
void R(int &root){
	int tmp = node[root].lc;
	node[root].lc = node[tmp].rc;
	node[tmp].rc = root;
	updateHeight(root);
	updateHeight(tmp);
	root = tmp;
}
void insert(int &root, int x){
	if(root == -1){
		root = newNode(x);
		return;
	}
	if(x < node[root].data){
		insert(node[root].lc, x);
		updateHeight(root);
		if(getBalanceFactor(root) == 2){
			if(getBalanceFactor(node[root].lc) == 1){	//LL
				R(root);
			}else if(getBalanceFactor(node[root].lc) == -1){	//LR
				L(node[root].lc);
				R(root);
			}
		}
	}else{
		insert(node[root].rc, x);
		updateHeight(root);
		if(getBalanceFactor(root) == -2){
			if(getBalanceFactor(node[root].rc) == -1){	//RR
				L(root);
			}else if(getBalanceFactor(node[root].rc) == 1){	//RL
				R(node[root].rc);
				L(root);
			}
		}
	}
}
int create(){
	int root = -1;
	for(int i = 0; i < n; ++i) insert(root, input[i]);
	return root;
}
int main(){
	scanf("%d", &n);
	for(int i = 0; i < n; ++i)	
		scanf("%d", &input[i]);
	int r = create();
	printf("%d", node[r].data);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值