首页 > 其他分享 >平衡树Splay与FHQ

平衡树Splay与FHQ

时间:2022-08-23 01:11:15浏览次数:47  
标签:rotate int tree 儿子 Splay 父亲 平衡 now FHQ

树剖的未来会补的(卑微)。

这里想讲讲平衡树,因为看着高级,可以证明我学过OI。

我们先了解下 \(BST\),也就是平衡二叉树。

他的概念是,对于每一个非叶子结点,他的左儿子一定小于当前节点,右儿子必定大于当前节点。

类似于如下图,就是一个好看的 \(BST\):

image

那我们现在对平衡二叉树有了深入的了解了,我们就开始进行平衡树的讲解。

一:平衡树解决的问题类型:

1.插入(删除)一个数

2.查询某个数的排名

3.查询某个排名所对应的数

4.查询某个数的前驱(后驱)

二:Splay

1.rotate 操作

分为左旋和右旋,我们偷一张图看一下:

image

我们将 x 右旋,就是将 x 的父亲 (y) 变成 x 的右儿子,x 的右儿子变成 y 的左儿子,x 变为 R 的右儿子。

我们将 y 左旋,得到的结果和上面一样。

那么我们可以轻松写出 rotate 函数了:

inline void rotate(int x) {
	int idx = check(x);//x作为y的哪个儿子
		int f = tree[x].f, idf = check(f);//y和y作为R的哪个儿子
		int sonx = tree[x].son[idx ^ 1];//x的儿子(与x作为的儿子反着)
		int ff = tree[f].f;//y的父亲
		
		connect(sonx, f, idx);//将x的儿子变成y的儿子
		connect(f, x, idx ^ 1);//将x的父亲变成x的儿子
		connect(x, ff, idf);//将x变为原来y的父亲的对应儿子
		
		update(f);
		update(x);//修改当前节点子树的大小
}

2.splay 函数

Splay 的核心,不然也不配命名为 splay。

主要就是进行旋转,将 u 转到 v 的上。

那么我们分三种情况:

1.v 是 u 的父亲,如下图:

image

我们只需要将 u 转一下即可:

image

2.u 作为 u 的父亲 k 的左(右)儿子, k 也作为 k 的父亲 v 的左(右)儿子,如下图:

image

我们需要先旋转 k,再旋转 u:

image

3.u 作为 u 的父亲 k 的左(右)儿子, k 也作为 k 的父亲 v 的右(左)儿子,如下图:

image

我们需要连选 2 次 u:

image

那么这样,我们可以很容易得到 splay 函数的代码:

inline void splay(int u, int v) {
	int fv = tree[v].f;
		
	while (fv != tree[u].f) {
		int fu = tree[u].f;
			
		if (fv == tree[fu].f) rotate(u);//v的父亲是u的父亲的父亲,即v是u的父亲		
		else if (check(u) == check(fu)) rotate(fu), rotate(u);//u和u的父亲分别同属于他们父亲的同种儿子
		else rotate(u), rotate(u);//与上面相反
	}
}

3.处理操作

1.插入:

那么是很显然的,只需要判断是否是相同的数即可。

相同的数,直接在频率上加一即可,否则建立新节点。

代码如下:

inline int add(int x, int fa) {
	tree[++ siz].data = x;
	tree[siz].f = fa;
	tree[siz].cnt = tree[siz].sum = 1;

	return siz;
}//添加一个节点

void push(int x) {
	int sign = 0, nxt;

	tot ++;

	if (! root) root = add(x, 0);//总得先有根节点吧……
	else {
		int now = root;

		while (now) {
			tree[now].sum ++;

			if (tree[now].data == x) {
				tree[now].cnt ++, sign = now;

				break; 
			} //已经有过这个数字,就将cnt++,位置标记

			nxt = tree[now].data < x ? 1 : 0;

			if (! tree[now].son[nxt]) {
				sign = tree[now].son[nxt] = add(x, now);

				break;
			}//这个节点还没有数字,就将这个数字差到当前节点

			now = tree[now].son[nxt];
		}
	}

	splay(sign, root);
}

2.删除:

标签:rotate,int,tree,儿子,Splay,父亲,平衡,now,FHQ
From: https://www.cnblogs.com/fogleaf/p/16614769.html

相关文章

  • display: flex,弹性布局
    实现一个商品详情的布局效果,左边图片右边文字标题和描述,采用display:flex,弹性布局,code如下:<html><head><title>我的第一个HTML页面</title><style>.list{......
  • 平衡二叉树
    1.为什么需要平衡二叉树?二叉排序树可能的存在的问题给你一个数列{1,2,3,4,5,6},要求创建一颗二叉排序树(BST),并分析问题所在.上图BST存在的问题分析:左子树全部为......
  • 后缀数组 & 后缀平衡树
    后缀数组&后缀平衡树PPT:【腾讯文档】后缀数组——钱贵宁后缀数组是什么本质上是对一个字符串的所有后缀进行排序例如字符串abbcaba,我们按长度顺序列出它的所有后......
  • splay树
    splay树概念splay树也是一种二叉查找树,同时也会通过旋转的操作保证一定的平衡。与普通的平衡树(AVL)相区别的是它可以将需要的节点不断向根节点旋转,这个过程被称作伸展......
  • Flex 布局 display:flex 与 inline-flex 区别
    1.Flex布局 display:flex.bigbox{width:500px;height:400px;background:#ff0000;display:flex;}.smallbox{width:100px;height:100p......
  • 大数据Hadoop之——Hadoop HDFS多目录磁盘扩展与数据平衡实战操作
    目录一、概述二、HadoopDataNode多目录磁盘配置1)配置hdfs-site.xml2)配置详解1、dfs.datanode.data.dir2、dfs.datanode.fsdataset.volume.choosing.policy3、dfs.datanod......
  • 【数据结构】红黑树与平衡二叉树的区别以及原理详解(附图解)
    引用网址:https://blog.csdn.net/weixin_44780082/article/details/112239269文章目录前言一、什么是红黑树1.1平衡二叉树1.2红黑树1.3平衡二叉树和红黑树的区别二、红黑......
  • AVL树的根(平衡二叉搜索树)
    https://www.acwing.com/problem/content/1554/思路:感觉这个左旋,右旋有些抽象,不好理解记忆,硬记也不好,当整个代码不算难写,因为很多部分都是堆成的。#include<iostream>......
  • CSS-关于display:inline、block、inline-block的差别
    什么是display(显示模式)?每一个html标签元素都会有一个预设的display属性,标签基本上大部分可分为两种显示模式,一种是行内元素(inline),另一种为区块元素(block),我们可以......
  • 172 树套树 线段树套平衡树
    视频链接:LuoguP3380【模板】二逼平衡树(树套树)//需要开O2#include<iostream>#include<algorithm>usingnamespacestd;#defineN2000010#defineINF21474836......