zoukankan      html  css  js  c++  java
  • 【GXZ的原创】平衡树性能测试

    本文作者为 GXZlegend ,转载请注明 出处 ,谢谢!


    〇、序言

    前些日子闲的蛋疼做了个平衡树性能测试。。。

    主要是因为学会的平衡树越来越多,做题时却不知道写哪个。。。

    本想结合效率和代码复杂度来决定通常情况下写哪个,

    然而在网上没有查到有关平衡树性能的相关信息(也许是我查的姿势不太对吧。。。)

    于是最终决定自己动手测试,造福自己和他人,毕竟时间是检验真理的唯一标准嘛。。。

    废话不多说,直接开始~

    一、测试成员(按字典序从小到大排序)

    Multiset

    SBT

    Splay

    Treap

    替罪羊树

    权值线段树+动态开点

    权值线段树+离线离散化

    非旋转Treap

    另外为了卖萌还加入了BST(逃

    二、测试题目

    支持$10^6$次插入一个$[-10^7,10^7]$范围内的数、删除一个当前序列中的数。

    这里之所以没有选择各种各样的查询操作,是因为平衡树的瓶颈不在于一般BST的查询操作。只有插入和删除才能体现出平衡树的效率。

    三、测试数据

    共放了12组测试数据。

    其中1、2号数据是随机数据(1号只有插入,2号在插入后删除掉);

    3~8号数据是按某一特定顺序将1~n(或n/2)这些数插入(并删除);

    9号数据是插入1~n/2后不断插入并删除$10^7$&$-10^7$;

    10、11号数据是插入1、-1、2、-2…和n/2、-n/2、n/2-1、-(n/2-1)…;

    12号数据是插入n个1。

    具体的数据可以在下面的测试包中查看。

    四、测试结果

    测试环境为GXZ的电脑

    使用Win10系统,g++4.8.4,并在Lemon下进行评测。评测结果如下:

    注:总时间不具有非常大的参考价值!

    注:总时间不具有非常大的参考价值!

    注:总时间不具有非常大的参考价值!

    开O2:

    不开O2:

     

    五、具体描述与分析(顺序为不开O2总时间倒序)

    1.非旋转Treap真心慢。。。而且最慢的是随机数据1、2号点,其中只有插入的1号点更慢一些。与其功能相似的Splay比其发挥更好一些。构造数据的效率还好(其中11号点稍微慢一些)。非常吃数据。

    2.替罪羊树作为倒数第二可能不服,不过事实上替罪羊树在随机数据上表现良好,而在构造数据上表现得稍微差一些。总体上不是很吃数据。

    3.权值线段树+离散化在不开O2情况下很慢,但是开O2情况下效率仅次于权值线段树+动态开点。因此其效率取决于排序的复杂度,不吃数据。

    4.Multiset效率和想象中一样,开O2时飞起,不开O2时奇慢。。。(想到我的NoiD1T2,哈希非要多个map,白白挂了40' QAQ)不吃数据。

    5.Splay在随机数据上效率极低(仅略优于非旋转Treap),而在构造数据上跑得飞快。具体原因是在插入时把插入的数旋转了上去,使得下次插入复杂度变为近似$O(1)$。非常吃数据。

    6.Treap在随机数据上较慢,其余效率较高。吃数据。(另外一个小插曲,在Linux下Treap非常快,效率接近于权值线段树+动态开点,猜想可能与随机数的范围有关。然而我在Windows下改用了rand()*rand()却发现更慢了。。。)

    7.SBT随机数据比Treap略快,构造数据比Treap略慢。。。略吃数据。

    8.权值线段树+动态开点是最快的“平衡树”,所有数据都较快,略吃数据。

    9.BST不解释,随随便便即可卡掉。

    六、对比总结

    对于任何情况,权值线段树都是最快的,并且也是最好写的。它的唯二缺点:不支持定点插入、空间消耗较大(作为树套树内层时多1个log)。但是它的高效以及支持多棵同时二分,使得它的用途非常之广泛,大多数情况可以代替Treap和SBT。

    SBT和Treap的效率不会差很多,因此不必纠结于学哪种,掌握较简单的就行(个人倾向于SBT一些)

    在不开O2情况下少用set,开O2时可以大胆使用。

    尽量不直接使用替罪羊树,个人建议替罪羊树的唯一使用情况就是放到树套树的外层(无旋转避免了pushup)

    Splay不要用于维护全序集,最好用于维护有序序列,效果较好。

    非旋转Treap效率真的不如Splay,唯一好处就是时间复杂度非均摊,可以可持久化

    七、测试包下载

    https://pan.baidu.com/s/1geQGMEf

    希望大家再写平衡树时就有一个参考辣~

  • 相关阅读:
    【LeetCode OJ】Remove Element
    【LeetCode OJ】Remove Duplicates from Sorted Array
    【LeetCode OJ】Swap Nodes in Pairs
    【LeetCode OJ】Merge Two Sorted Lists
    【LeetCode OJ】Remove Nth Node From End of List
    【LeetCode OJ】Two Sum
    【LeetCode OJ】Majority Element
    最长公共子序列问题
    php fopen与file_get_contents的区别
    PHP 技巧集合
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7565067.html
Copyright © 2011-2022 走看看