关于Treap的学习感受

                                                                       

好了我就很愉快的回来补坑了~

Treap也是一种平衡树,它较普通二叉查找树而言,每个节点被赋予了一个新的属性:优先级(没错就是类似优先队列的优先),对于Treap中的每个结点,除了它的权值满足二叉查找树的性质外,它的优先级还满足堆性质,也就是结点的优先级小于它所有孩子的优先级。

换句话说,从权值上看,Treap是一个二叉查找树;从优先级上看,Treap是一个堆。所以我们发现Treap其实可以看做是Tree+Heap。

我们发现普通BST会不平衡是因为有序的数据会使查找路径退化成链,而随机数据使其退化的概率非常小。因此我们在Treap中赋予的这个优先级的值采用随机生成的办法,这样Treap的结构就趋于平衡了。(如果脸黑怎么办(逃))

如果我们假设所有点的权值与优先级都互不相同,那么Treap的形态是唯一确定的。

我们考虑在所有结点中找到优先级最小的点,则它一定是Treap的根,而权值小于它的点会在根的左子树,大于它的点会在根的右子树,这就可以递归下去构建Treap。这个建立过程与快速排序类似,因此Treap的期望深度与快排的期望递归层数一样都是O(log n)的。

为了使Treap满足性质,有时我们不可避免地要对结构进行调整,而我们调整的方式是旋转。在维护Treap的过程中,我们会出现两种旋转:左旋与右旋。

左旋一个子树,这个子树的根节点为x,则旋转后会把x变为这个子树的新根的左儿子,x的右儿子会成为子树新的根。右旋一个子树,这个子树的根节点为x,则旋转后会把x变为这个子树的新根的右儿子,x的右儿子会成为子树新的根。(详细图解见Splay,传送门:https://blog.csdn.net/g21glf/article/details/82931486)。

显然旋转后这个Treap仍然满足权值的BST性质,因此这个旋转操作就保证了,若我们满足了BST性质,那么不满足堆性质的部分我们可以通过旋转,使其满足堆性质。旋转的意义也正是在此,使不满足堆序的两个节点通过调整位置,重新满足堆序,而不改变BST性质。

Treap的各种操作与BST无异,唯一有些不同的就是插入操作。我们从根节点开始插入,如果要插入的值小于当前节点的值,那么我们要在当前节点的左子树进行插入;否则我们要在当前节点的右子树进行插入; 若当前节点是个空节点, 则我们在这个位置上新建一个节点。插入之后新建的这个节点可能会使Treap不满足堆性质,那么我们就通过旋转操作不断调整,这个步骤可以通过递归来实现。

在删除时,我们首先需要在Treap上走,找到需要删除的那个节点,接着我们可以利用旋转操作不停调整需要删除的这个节点在树中的位置。若删除节点为叶节点,那么我们可以直接删除; 若它只有一个儿子, 那么我们直接让那个儿子代替这个被删除的节点即可。 否则,若删除节点左儿子的优先级小于删除节点右儿子优先级,那么我们对删除节点进行右旋,让左儿子成为新的子树的根;反之同理。直到它变为前两种情况。

由于Treap的树高是期望O(log n)的,所以它各个操作的期望复杂度也是O(log n)。

【贴代码~】

更新
void update(const int &k)
{tr[k].size=tr[lc[k]].size+tr[rc[k]].size;
}
右旋
void zig(int &k)
{int y=lc[k];lc[k]=rc[y];rc[y]=k;size[y]=size[k];update(k);k=y;
}
左旋
void zag(int &k)
{int y=rc[k];rc[k]=lc[y];lc[y]=k;size[y]=size[k];update(k);k=y;
}
插入
void insert(int &k,int &key)
{if(!k){k=++pool;key[k]=key;pri[k]=rand();cnt[k]=size[k]=1;lc[k]=rc[k]=0;return ;}else++size[k];if(k.key==key)++cnt[k];else{if(key<k.key){insert(lc[k],key);if(pri[lc[k]]>pri[k])zig(k);}else{insert(rc[k],key);if(pri[rc[k]]<pri[k])zag(k);}}return ;
}
删除
void del(int &k,int &key)
{if(k.key==key){if(cnt[k]>1)cnt[k]--,size[k]--;else{if(!lc[k]||!rc[k])k=lc[k]+rc[k];else{if(pri[lc[k]]<pri[rc[k]])zig(k),del(k,key);elsezag(k),del(k,key);}}}else--size[k];if(key<k.key)del(lc[k],key);elsedel(rc[k],key);return ;	
}
询问优先级
int queryrank(const int &key)
{int x=rt,res=0;while(x){if(key==key[x])return res+size[lc[x]]+1;if(key<key[x])x=lc[x];elseres+=size[lc[x]]+cnt[x],x=rc[x];}return res;
}
寻找第k大
int querykth(int k)
{int x=rt;while(x){if(size[lc[x]]<k&&size[lc[x]]+size[x]>=k)return x.key;if(size[lc[x]]>=k)x=lc[x];elsek-=size[lc[x]]+cnt[x],x=rc[x];}return 0;
}
求前驱
int querypre(const int &k)
{int x=rt,res=-INF;while(x){if(key[x]<key)res=key[x],x=rc[x];elsex=lc[x];}return res;
}
求后继
int querysuf(const int &k)
{int x=rt,res=INF;while(x){if(key[x]>key)res=key[x],x=lc[x];elsex=rc[x];}return res;
}

以上就是个人关于Treap的一些感悟,后续会补坑。。。

转载于:https://www.cnblogs.com/Ishtar/p/10010833.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/464793.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2022年考研结束了

为期两天的研究生考试结束了。我没参加研究生考试&#xff0c;所以对研究生考试的压力不从得知&#xff0c;我从一个外人的角度来看&#xff0c;这无非就是一个简单的考试&#xff0c;考上了欢喜雀跃&#xff0c;考不上嘛&#xff0c;我就会说&#xff0c;大不了来年再考一次&a…

挂“洋头”卖奶粉,澳优还要欺骗好久

澳优奶粉近期被质疑非进口产品&#xff0c;公司总部实为湖南一家贴牌商。该奶粉生产商澳优乳业公司回应称其为“国外产品与本国品牌相结合”的国际化企业。但奶粉包装仍被质疑误导消费者&#xff0c;且售价偏高&#xff0c;澳优方称“与其高端品质相比只属于中上水平”&#xf…

DefWindowProc

简介 函数功能&#xff1a;该调用DefWindowProc函数时使用窗口过程接收的相同参数。函数原型&#xff1a;LRESULT DefWindowProc&#xff08;HWND hWnd&#xff0c;UINT Msg&#xff0c;WPARAM wParam&#xff0c;LPARAM IParam&#xff09;&#xff1b;功能 DefWindowProc这个…

mysql通过局域网访问数据库_MySQL数据库之局域网内访问同一个mysql数据库

本文主要向大家介绍了MySQL数据库之局域网内访问同一个mysql数据库 &#xff0c;通过具体的内容向大家展现&#xff0c;希望对大家学习MySQL数据库有所帮助。局域网内访问同一个mysql数据库。一、运行cmd&#xff0c;输入mysql -u root -p。二、输入mysql数据库密码&#xff0c…

排序算法之冒泡排序(C/C++)

冒泡法排序&#xff1a;平均时间复杂度O(n*n) 最差时间复杂度O(n*n) 比较相邻的元素。如果第一个比第二个大&#xff0c;就交换他们两个。对每一对相邻元素作同样的工作&#xff0c;从开始第一对到结尾的最后一对。在这一点&#xff0c;最后的元素应该会是最大的数重复以上工…

约翰·冯·诺依曼:一个向上帝买了挂的男人!!

来源|David 小咸鱼/新智元约翰冯诺依曼是20世纪最有影响力的人物之一。从原子弹&#xff0c;到计算机、再到量子力学、气候变化&#xff0c;你可能很难再找出像这样对我们今天的世界和生活影响更大的科学家了。在20世纪的天才中&#xff0c;有几个杰出的人物&#xff1a;爱因斯…

mysql pdo prepare_PDO::prepare

PDO::preparePDO::prepare — 准备要执行的SQL语句并返回一个 PDOStatement 对象(PHP 5 > 5.1.0, PECL pdo > 0.1.0)说明语法public PDOStatement PDO::prepare ( string $statement [, array $driver_options array() ] )为 PDOStatement::execute() 方法准备要执行的S…

使用webpack配置react并添加到flask应用

学习react&#xff0c;配置是很痛苦的一关&#xff0c;虽然现在有了create-react-app这样方便的工具&#xff0c;但是必须要自己配置一遍&#xff0c;才能更好地进行项目开发。 首先要明确一个概念&#xff1a;react的文件必须经过编译才能被浏览器识别&#xff0c;因此我们需要…

POJ 2976 Dropping Tests

http://poj.org/problem?id2976 题目大意&#xff1a;给定n个二元组(a,b)&#xff0c;扔掉k个二元组&#xff0c;使得剩下的 最大。 这两天一直在搞分数规划&#xff0c;有了前两道题&#xff08;3621、2728&#xff09;&#xff0c;这道题就是完完全全的大水题了。 设 r100…

回调函数这个是什么鬼?

这是一个同学在微信给我提问的问题。要搞清楚回调函数&#xff0c;我们首先要搞清楚函数&#xff0c;函数其实就是一个地址&#xff0c;这个地址描述了这个函数在内存中的位置。但是函数和变量也是一样的&#xff0c;有类型&#xff0c;对变量来说&#xff0c;变量会分成各种类…

一个整数转换成字符串(C/C++自己写的算法)

自己写的一个算法&#xff1a;将一个int型数转换为string char *itoa(int num, char *str){assert(NULL ! str);int i1, j0;if (num < 0){str[j]-;num (-1)*num;}if (0 num){str[j] 0;str[j] \0;return str; }while (! (num/i < 10)){i i*10;}while (num > 0){st…

mysql模糊查询与预编译_mysql预编译模糊查询恶心了我一天的时间,终于弄好了。但是还有一点不明白。如下:...

不用这么麻烦&#xff0c;你可以定义个boolean的变量&#xff0c;用来记录传参是不是description&#xff0c;如果是&#xff0c;在paramList的循环里做模糊拼接&#xff0c;不是&#xff0c;就不用boolean descFlagfalse; //标记传来的参数是否为description&#xff0c;为后面…

小米12比我的小米10还便宜

昨天晚上&#xff0c;小米发布会发布了新的小米12手机&#xff0c;价格很亲民&#xff0c;比我两年前买的小米10还便宜。这还不算&#xff0c;小米12比小米10还更好看。小米在尝试曲面屏之后&#xff0c;终于觉得曲面屏不再是一个可以用来炫耀的卖点了。我自己的小米10曲面屏&a…

庆祝51CTO六周年:资源牛人有奖比拼,生日当天疯狂送豆!(已结束)

2011年8月15日&#xff0c;是51CTO成立6周年的日子。为庆祝这一盛典&#xff0c;特推出此活动。一、活动时间&#xff1a;2011年8月5日——2011年8月25日 24:00二、活动奖项及规则&#xff1a;1、资源牛人金奖&#xff1a;入围资源牛人排行榜前十名的Down友已经产生&#xff0c…

Centos7:mysql5.6安装,配置及使用(RPM方式)

1.首先安装好jdk环境,本机所用环境为jdk1.8 2.卸载MariaDB(Centos7自带)与Mysql 2.1卸载:MariaDB #rpm -qa | grep -i mariadb //查询安装的MariaDB#rpm -e --nodeps 查到软件名 //卸载相关MariaDB的所有软件#find / -name mariadb#whereis mariadb //查找是否有相关配置目录及…

判断一个单链表中是否存在环

#判断一个单链表中是否存在 环。 #设置两个指针(fast, slow)&#xff0c;初始值都指向头&#xff0c;slow每次前进1步&#xff0c;fast每次前进2步&#xff0c; 大概的思路如下&#xff1a; 如果链表存在环&#xff0c;则fast必定先进入环&#xff0c;而slow后进入环&#xff…

mysql3.5 所有表_mysql学习笔记3.5

紧接着笔记3的训练介绍一个对于我来说的比较难的难点&#xff01;&#xff01;&#xff01;&#xff01;select * from sc;select student.sno,sname,avg(grade) as平均分fromstudent,scwhere student.snosc.snogroup bystudent.snohaving avg(grade)>90/*这一个条件我竟然忘…

CPU上电后加载程序的流程 | 基于RK3399

芯片上电解复位之后执行的第一段程序&#xff0c;在芯片中称之为Bootrom loader。这部分程序在芯片制造过程中固化到其内部的ROM空间&#xff0c;具备只读属性&#xff0c;在实际使用过程中无法修改这部分内容&#xff0c;这部分程序的知识产权也仅归属于芯片公司所有。其实&am…

IPv6与IPv4的区别

Technorati 标签: Hank--network porter■第一个就不说哈&#xff0c;32bit直接升级到128bit了。 从2的32次方升级到2的128次方了&#xff0c;地球上的每一粒沙子都可以分到一个IP地址。这个是IPv6最拉风的地方. ■在IPv6中&#xff0c;路由器不能用自动配置机制来配置接口&…

前端安全系列(一):如何防止XSS攻击?

前端安全 随着互联网的高速发展&#xff0c;信息安全问题已经成为企业最为关注的焦点之一&#xff0c;而前端又是引发企业安全问题的高危据点。在移动互联网时代&#xff0c;前端人员除了传统的 XSS、CSRF 等安全问题之外&#xff0c;又时常遭遇网络劫持、非法调用 Hybrid API …