Woc,考场(面试)忘记打平衡树怎么办,Trie救你命
Woc,考场(面试)忘记打平衡树怎么办,Trie救你命
文本只发布于博客园,其他地方出现本文均是未经许可的盗版。
算法导入
众所周知平衡树很难打(大佬除外),还老是调错。万一这种事情发生在关键时刻你就GG了。那我们怎么办呢?
从本质上介绍,平衡树作用就是维护一个有序的序列(关系)。很多操作我们用vector(数组)+lower_bound(二分查找),都可以实现。但是vector插入不便,导致序列维护不便。如果用list(链表)代替vector,那么查找又很慢。怎么办呢?
考虑到我们一般都是维护一个整数的排序,那么我能不能找到一种支持动态排序的数据结构。堆可以进行动态处理,但是只有第一个是有序的,他的子节点只能满足比他小(大)。
难道除了平衡树我们就没有别的方法了吗?答案是有的。看看下面的树。
Root-->A["0"]
Root-->B["1"]
A["0"]-->C["0"]
A["0"]-->D["1"]
B["1"]-->E["0"]
B["1"]-->F["1"]
C["0"].->G["0"]
D["1"].->H["1"]
E["0"].->I["2"]
F["1"].->K["3"]
这不是01Trie(字典树)吗?这能当平衡树????
别急,仔细看看。
这个Trie是不是左子树小于右子树?
好像是啊
再想想为什么?
应该是二进制关系,左边的节点当前这一位是0,后面更小的位再大,也不可能比当前这一位是1的大了。
没错
你再想想,Trie字典树是不是可以动态插入?
好像是
所以我们可以利用这种关系实现平衡了。甚至我们还能很简单的实现可持久化。
但是不难看出有几个缺点。
空间要比一般平衡树大,一个int32最坏情况需要32个int32去记录他。当然实际情况也不可能都是这样。实际运用中有许多的重复节点,可以重复利用的。知道数字范围的时候也能调整树高解决。在一道平衡树的模板题,内存是FHQ_Treap的1.7倍,速度更快,内存是Splay的2/3,速度差不多。是红黑树的4/5,速度是1/2。
不能直接输入负数(除非你建树的时候把符号位也建立进去,不过这样你也不好解决大小查找,毕竟负数是补码,情况和正数相反)。你需要加一个比较大的数值使得负数变为正数。
不能进行序列操作(不过支持这个操作的平衡树也不多)。
当然直接用Trie也不行,你还需要维护几个信息,否则你没法实现一些功能。
你需要维护
- 每个节点对应子树大小
- 每个叶子节点的值的数量(为了支持重复值插入)
代码实现
提前定义
这里我定义树高为25层
const int MAXLOG=25;
节点信息
需要保存两个儿子,节点子树大小,叶子节点计数
代码如下
struct node
{
int ch[2];
int sze, cnt;
} Tree[MAXLOG];
int p; //模拟一个内存池,这是对应的顶。
插入&删除 操作
插入操作其实和一般树没什么区别,唯一不同的地方就是你需要维护节点的sze和cnt信息。
删除操作和插入操作其实一样,区别就是一个做加法,一个做减法。
代码如下
void updata(int x, int offset) // 插入/删除 offset个x,插入正,删除负
{
int now = 0; //0是根
for (int i = MAXLOG - 1; i >= 0; i--)
{
bool now_bit = (x & (1 << i) != 0); //第i位的数值
if (!Tree[now].ch[now_bit] == 0) //指向空,需要分配子节点
Tree[now].ch[now_bit] = ++p;
now = Tree[now].ch[now_bit];
Tree[now].sze += offset; //这条子树链上的节点都需要
}
Tree[now].cnt += offset; //跑到叶子节点了
}
数取排名
代码也是比较简单,就是注意当节点为NULL的时候就可以退出了。
int get_rank(int x) //获取比x小的数的数量,不包括本身
{
int now = 0; //0是根
int ans = 0;
for (int i = MAXLOG - 1; i >= 0; i--)
{
bool now_bit = ((x & (1 << i)) != 0); //第i位的数值
if (now_bit == 1) //处于大的那一边
ans += Tree[Tree[now].ch[0]].sze; //把比自己小的那些加上
now = Tree[now].ch[now_bit];
if (now == 0) //别忘了,这里的0是空的意思
break;
}
return ans;
}
排名取数
int get_kth(int k) //通过排名大小
{
int now = 0; //0是根
int ans = 0;
for (int i = MAXLOG - 1; i >= 0; i--)
{
int temp = Tree[Tree[now].ch[0]].sze; //看看自己前面有多少
if (k <= temp) //还在更前面
now = Tree[now].ch[0];
else //在自己后面
{
k -= temp; //更新相对在右子树的位置
now = Tree[now].ch[1];
ans |= (1 << i); //可以确定这一位是1
}
if (now == 0) //别忘了,这里的0是空的意思
break;
}
return ans;
}
求前驱&后继
这个也是草鸡简单
int pre(int x)
{
return get_kth(get_rank(x));
}
int nxt(int x)
{
return get_kth(get_rank(x + 1) + 1);
}
更多
由于这个树是基于Trie的,Trie能可持久化,这个也能。不过可持久化我们以后再讲。
完整代码下载地址:https://files.cnblogs.com/files/blogs/694685/TrieBST.7z
Woc,考场(面试)忘记打平衡树怎么办,Trie救你命的更多相关文章
- [学习笔记]可持久化数据结构——数组、并查集、平衡树、Trie树
可持久化:支持查询历史版本和在历史版本上修改 可持久化数组 主席树做即可. [模板]可持久化数组(可持久化线段树/平衡树) 可持久化并查集 可持久化并查集 主席树做即可. 要按秩合并.(路径压缩每次建 ...
- 可持久化数据结构(平衡树、trie树、线段树) 总结
然而好像没有平衡树 还是题解包: T1:森林 树上主席树+启发式合并. 然而好像知道标签就没啥了.在启发式合并时可以顺手求lca 然而这题好像可以时间换空间(回收空间) T2:影魔 难点在于考虑贡献的 ...
- 笔试算法题(39):Trie树(Trie Tree or Prefix Tree)
议题:TRIE树 (Trie Tree or Prefix Tree): 分析: 又称字典树或者前缀树,一种用于快速检索的多叉树结构:英文字母的Trie树为26叉树,数字的Trie树为10叉树:All ...
- 百度NLP二面-电话面
实验室项目:1.实验室方向 2.用两分钟介绍自己的项目,创新点在哪里 个人项目: 1.自己实现的贝叶斯分类器,目的,怎么做的 2.怎么计算各个分类的先验.(因为我使用的训练预料是每个分类10篇 ...
- 百度NLP二面
实验室项目:1.实验室方向 2.用两分钟介绍自己的项目,创新点在哪里 个人项目: 1.自己实现的贝叶斯分类器,目的,怎么做的 2.怎么计算各个分类的先验.(因为我使用的训练预料是每个分类10篇 ...
- HNOI2016 游记
题外 忽然想起去年的HNOI2015总结里好像引了一句诗: 此情可待成追忆,只是当时已惘然. Day0 唔,感觉不知道想些什么,只是觉得其实还没有做好准备,想学的东西学的仓促,想复习的东西,也只能看一 ...
- Noip模拟58 2021.9.21(中秋祭&&换机房祭)
第一次在学校过中秋节,给家里人视频电话,感觉快回家了很开心, 然后还吃了汉堡喝饮料非常爽,颓废了一会儿还换了新机房,$Linux2.0$非常dei,少爷机也非常快, 发现好像测评机又成了老爷机,这就是 ...
- NOIP 2017 游记?
Day -1 晚上被dg谈了谈人生,没有卵用 Day 0 早上又被老吕教训了一遍,想打板子,打印机还坏了,老吕又奶了一波题,后来发现一个都没中.之后就出发了,中午吃了点肯德基,妈妈来了,给我了个小袋子 ...
- 浅谈Hash在多个字符串匹配类型问题中的应用
在生活中们有时会遇到一些有关字符串匹配的问题. 这时打暴力往往显得很愚蠢,效率低下. 所以就需要一些算法和数据结构来提高效率. Hash Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把 ...
随机推荐
- CentOS-Docker安装MongoDB(单点)
下载镜像 $ docker pull mongo 创建相关目录 $ mkdir -p /usr/mongo/data /usr/mongo/dump 运行镜像 $ docker run --resta ...
- Laravel + Swoole 打造IM简易聊天室
最近在学习Swoole,利用Swoole扩展让PHP生动了不少,本篇就来Swoole开发一款简易的IM聊天室 应用场景:实现简单的即时消息聊天室. (一)扩展安装 pecl install swool ...
- XML技术
XML是一种可扩展标记语言,用来标记数据.定义数据类型,1998年由W3W发布1.0.版本,与HTML语言相比,可以自定义可扩展标签格式,但是语法严格. XML可以用来存储数据,可移植性强,主要充当配 ...
- 从源码角度谈谈MySQL "Too many open files"错误的根本原因
"Too many open files"是一个比较常见的错误,不仅仅是在 MySQL 中.只要是在 Linux 中启动的进程,都有可能遇到这个错误. 究其原因,是进程打开的文件描 ...
- [004] - JavaSE面试题(四):JavaSE语法(2)
第一期:Java面试 - 100题,梳理各大网站优秀面试题.大家可以跟着我一起来刷刷Java理论知识 [004] - JavaSE面试题(四):JavaSE语法(2) 第1问:重载(overload) ...
- 解决Git Clone速度过慢的方法
Git Clone速度慢,原因很简单,默认的源是国外的,只需要使用国内源,速度就起飞了(当然,也没有太快,至少可以忍受了).使用方法很简单,在clone某个项目的时候将github.com替换为git ...
- HTML5-CSS(四)
一.CSS3 渐变效果 (1)CSS3 提供了 linear-gradient 属性实现背景颜色的渐变功能.首先,我们先看一下它的样式表,如下: //两个必须参数background-image: l ...
- 分享一个自己画div的技巧
分享一个自己画div的技巧 笔者是小白,前端不是很懂.现在想总结下自己画div布局的小技巧和思路. 先对着设计图把div给好好框选出来 我个人觉得这一步是很重要的,要先分析大局,再细节处理.一定要先决 ...
- MYSQL一个设备上的主从复制实现-windows
只记录一次在一个设备上实现mysql主从复制的过程,很详细,建议收藏,用到的时候照着步骤做就可以,会记录所有需要注意到的细节和一些容易遇到的坑以及解决办法! 如果需要在同一台电脑(服务器)上实现mys ...
- WEB安全新玩法 [9] 重置密码之验证流程防绕过
一般来说,业务流程中出现多个操作环节时,是需要顺序完成的.程序设计者往往按照正常用户的操作顺序实现功能,而忽略了攻击者能够绕过中途环节,直接在后续环节上进行非法操作.iFlow 业务安全加固平台能够在 ...