【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

希望大家再寫平衡樹時就有一個參考辣~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM