首页 > 其他分享 >【模板】AVL树

【模板】AVL树

时间:2022-10-17 09:59:12浏览次数:74  
标签:lid val int AVL key rid id 模板


据说啊,AVL树 是第一种被发明的平衡树。

它在动态维护过程中,保证了左右子树高度差不超过 \(1\),

所以说是一种严格平衡的二叉查找树。

最重要的就是左旋、右旋以及左右旋、右左旋,

以及分情况讨论什么时候该做哪一种旋转。

void zig(int &id) {
	int rc = rid(id);
	//记录下右子节点(right child)
	rid(id) = lid(rc);
	lid(rc) = id;
	update(id);
	update(rc);
	id = rc;
}//右旋
void zag(int &id) {
	int lc = lid(id);
	//记录下左子节点(left child)
	lid(id) = rid(lc);
	rid(lc) = id;
	update(id);
	update(lc);
	id = lc;
}//左旋
void zig_zag(int &id) {
	zag(rid(id));
	zig(id);
}//右左旋
void zag_zig(int &id) {
	zig(lid(id));
	zag(id);
}//左右旋
void lgr(int &id) {
	if(h(lid(id))-h(rid(id)) >= 2) {
		if(h(lid(lid(id))) >= h(rid(lid(id)))) 
			zag(id);
		else 
			zag_zig(id);
	}
}//当左子树高度可能更大时
void rgl(int &id) {
	if(h(rid(id))-h(lid(id)) >= 2) {
		if(h(rid(rid(id))) >= h(rid(lid(id)))) 
			zig(id);
		else 
			zig_zag(id);
	}
}//反之

以上就是 AVL树 的核心了。

据说理论分析上 AVL树 比红黑树更快?

但是红黑树的小常数足以把这个小差距盖过去。

其实似乎 AVL树 实在是一种平平无奇的平衡树,

没有 TREAP 简单,没有 FHQ-TREAP 实用,没有 SPLAY 功能多,也没有 红黑树 快。

论暴力程度它也比不上朝鲜树。((


\(\textrm{luogu P6136 【模板】普通平衡树(数据加强版)}\)

不会有人刚刚才过这题罢

#include <iostream>
#include <algorithm>
const int N = 3e6+10;
struct AVL {
	int key, cnt;
	int lid, rid;
	int height, size;
} avl[N];
int avl_tot, root;
#define key(id) avl[id].key//键值
#define cnt(id) avl[id].cnt//数量
#define lid(id) avl[id].lid//左子节点
#define rid(id) avl[id].rid//右子节点
#define h(id) avl[id].height//子树高
#define s(id) avl[id].size//子树大小
#define mh(x,y) std :: max(h(x),h(y))
int new_node(int val) {
	key(++avl_tot) = val;
	lid(avl_tot) = rid(avl_tot) = 0;
	h(avl_tot) = s(avl_tot) = cnt(avl_tot) = 1;
	return avl_tot;
}
int update(int id) {
	s(id) = s(lid(id))+s(rid(id))+cnt(id);
	h(id) = mh(lid(id),rid(id))+1;
	return h(id);
}
void zig(int &id) {
	int rc = rid(id);
	//记录下右子节点(right child)
	rid(id) = lid(rc);
	lid(rc) = id;
	update(id);
	update(rc);
	id = rc;
}//右旋
void zag(int &id) {
	int lc = lid(id);
	//记录下左子节点(left child)
	lid(id) = rid(lc);
	rid(lc) = id;
	update(id);
	update(lc);
	id = lc;
}//左旋
void zig_zag(int &id) {
	zag(rid(id));
	zig(id);
}//右左旋
void zag_zig(int &id) {
	zig(lid(id));
	zag(id);
}//左右旋
void lgr(int &id) {
	if(h(lid(id))-h(rid(id)) >= 2) {
		if(h(lid(lid(id))) >= h(rid(lid(id)))) 
			zag(id);
		else 
			zag_zig(id);
	}
}//当左子树高度可能更大时
void rgl(int &id) {
	if(h(rid(id))-h(lid(id)) >= 2) {
		if(h(rid(rid(id))) >= h(rid(lid(id)))) 
			zig(id);
		else 
			zig_zag(id);
	}
}//反之
void ins(int &id,int val) {
	if(!id) {
		id = new_node(val);
		return;
	}
	if(key(id) == val) {
		++cnt(id);
		update(id);
		return;
	}
	if(key(id) < val) {
		ins(rid(id),val);
		update(id);
		rgl(id);
	} else {
		ins(lid(id),val);
		update(id);
		lgr(id);
	}
	update(id);
}
void del(int &id,int val) {
	if(!id) 
		return;
	if(key(id) > val) {
		del(lid(id),val);
		update(id);
		rgl(id);
	} else if(key(id) < val) {
		del(rid(id),val);
		update(id);
		lgr(id);
	} else {
		if(cnt(id) > 1) {
			--cnt(id);
			update(id);
			return;
		}
		if(lid(id)&&rid(id)) {
			int now = rid(id);
			while(lid(now)) 
				now = lid(now);
			cnt(id) = cnt(now);
			key(id) = key(now);
			cnt(now) = 1;
			del(rid(id),key(now));
			update(id);
			lgr(id);
		} else if(lid(id)) 
			id = lid(id);
		else if(rid(id)) 
			id = rid(id);
		else 
			id = 0;
	}
	if(id) 
		update(id);
}
int get_rks(int id,int val) {
	if(!id) 
		return 1;
	if(key(id) == val) 
		return s(lid(id))+1;
	else if(key(id) > val) 
		return get_rks(lid(id),val);
	else 
		return get_rks(rid(id),val)+s(lid(id))+cnt(id);
}
int get_val(int id,int rks) {
	if(s(lid(id)) >= rks) 
		return get_val(lid(id),rks);
	else if(cnt(id)+s(lid(id)) >= rks) 
		return key(id);
	else 
		return get_val(rid(id),rks-s(lid(id))-cnt(id));
}
int get_pre(int val) {
	int id = root;
	int res = 0;
	while(id) {
		if(key(id) == val) {
			if(lid(id)) {
				id = lid(id);
				while(rid(id)) 
					id = rid(id);
				res = id;
			}
			break;
		}
		if(key(id) <= val&&(key(id) > key(res)||key(res) <= 0)) 
			res = id;
		id = key(id) < val ? rid(id) : lid(id);
	}
	return key(res);
}
int get_suc(int val) {
	int id = root;
	int res = 0;
	while(id) {
		if(key(id) == val) {
			if(rid(id)) {
				id = rid(id);
				while(lid(id)) 
					id = lid(id);
				res = id;
			}
		}
		if(key(id) > val&&(key(id) < key(res)||key(res) <= 0)) 
			res = id;
		id = key(id) < val ? rid(id) : lid(id);
	}
	return key(res);
}
void init() {
	avl_tot = 0;
	root = 1;
	rid(root) = lid(root) = 0;
}
void dfs(int id) {
	if(lid(id)) 
		dfs(lid(id));
	printf("%d (%d %d) %d %d\n",id,lid(id),rid(id),cnt(id),key(id));
	if(rid(id)) 
		dfs(rid(id));
}
int n, m, opt, x;
int ans, final_ans;
void work_P3369() {
	init();
	scanf("%d",&n);
	for(int i = 1;i <= n;++i) {
		scanf("%d %d",&opt,&x);
		if(opt == 1) {
			if(avl_tot == 0) 
				root = new_node(x);
			else 
				ins(root,x);
		} else if(opt == 2) 
			del(root,x);
		else if(opt == 3) 
			printf("%d\n",get_rks(root,x));
		else if(opt == 4) 
			printf("%d\n",get_val(root,x));
		else if(opt == 5) 
			printf("%d\n",get_pre(x));
		else if(opt == 6) 
			printf("%d\n",get_suc(x));
		else {
			printf("DFS >> \n");
			dfs(root);
		}
	}
}
int new_n;
void work_P6136() {
	init();
	scanf("%d %d",&n,&m);
	for(int i = 1;i <= n;++i) {
		scanf("%d",&x);
		if(avl_tot == 0) 
			root = new_node(x);
		else 
			ins(root,x);
	}
	for(int i = 1;i <= m;++i) {
		scanf("%d %d",&opt,&x);
		x ^= ans;
		if(opt == 1) {
			if(avl_tot == 0) 
				root = new_node(x);
			else 
				ins(root,x);
		} else if(opt == 2) 
			del(root,x);
		else if(opt == 3) 
			final_ans ^= (ans = get_rks(root,x));
		else if(opt == 4) 
			final_ans ^= (ans = get_val(root,x));
		else if(opt == 5) 
			final_ans ^= (ans = get_pre(x));
		else if(opt == 6) 
			final_ans ^= (ans = get_suc(x));
		else {
			printf("DFS >> \n");
			dfs(root);
		}
	}
	printf("%d\n",final_ans);
}
int main() {
	#ifndef ONLINE_JUDGE
	freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);
	#endif
	work_P6136();
	return 0;
}

标签:lid,val,int,AVL,key,rid,id,模板
From: https://www.cnblogs.com/bikuhiku/p/Balanced_Tree-AVL.html

相关文章