• 【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

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

  • 相关阅读:
    C++ 类的多态一(virtual关键字--构造函数深刻理解)
    C++ 类的继承六(多继承的二义性--虚基类)
    C++ 类的继承五(类继承中的static关键字)
    C++ 类的继承四(类继承中的重名成员)
    C++ 类的继承三(继承中的构造与析构)
    C++ 类的继承二(赋值兼容性原则)
    C++ 类的继承一(访问控制)
    C++ 匿名对象产生场景
    WPF/ASP.NET:几个Prism中的术语
    Prism 5 + MEF中的ModuleCatalog.CreateFromXaml问题
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7565067.html
Copyright © 2020-2023  润新知