神一般的數據結構--可持久化treap


  原來聽說過可持久化treap,覺得最多就和可持久化線段樹一般可用程度。於是對於區間和序列問題就選擇使用線段樹和splay了,集合問題就選擇各種平衡樹和Splay。。。然后仔細的看了一下可持久化treap的操作和《范浩強談數據結構》的ppt,發現這個神一般的既好寫(zuo)又好看(wen)還好用(chi)的數據結構。

  首先這個東西很好寫,作為一個平衡樹,它沒有旋轉!!!是的,一點都沒有旋轉,rightturn,leftturn什么的去死吧,我們不需要旋轉。最基本的操作只有兩種,一種叫merge,一種叫split,merge是把兩個序列合並的操作,需要保證左邊的所有元素小於(廣義的小於,根據平衡樹的作用來確定)右邊的元素,合並時,treap的堆權值(我叫它key,但好像有人叫weight還有其他什么的,還是叫做堆權值一點歧義都沒有)要求被維護,則遞歸調用merge,如果現在的左樹堆權值小於右樹(假設是小根堆)則調用merge(左樹->rson,右樹),返回值(node*)作為新節點的右子樹,就是在左樹的右子樹插入右樹,因為右樹大於左樹,所以不會在左樹的左子樹遞歸調用,如果左樹堆權值大於右樹,則調用merge(左樹,右樹->lson),返回值作為新節點的左子樹,新節點的其他值等於原來的左樹根或者右樹根(具體是哪一個很好思考對吧,balbala就是這樣),然后返回這個新節點,注意一個hui常重要的地huang,返回的是新節點!也就是說每次merge其實新建了一條logN的鏈,所以說為什么叫可持久化treap呢,就是這個原因,只需要把每次操作的返回值存起來,就可以訪問歷史記錄了!Split操作是把一棵樹按權值分為兩棵,可以寫兩個函數分別返回左邊和右邊,這個也需要遞歸調用,大體思想是如果現在這個節點的權值與分割權值差的很遠(這是口頭表達)就遞歸調用下一層,否則新建一個節點,左右子樹中和分離無關系的直接掛上去,另一邊調用下一層split,然后返回這個新節點。然后,什么基本操作都寫好啦,沒有turn,沒有什么zig-zag。

  有了基礎操作,怎么insert和delete呢?很簡單,insert就是把原樹按新節點權值split成兩個,merge新節點和左邊,merge現在的左邊和右邊,搞定!還是沒有旋轉!

  delete差不多,split,split,然后不管(Delete)中間那單個元素,merge左右兩邊,搞定了,也沒有旋轉!

  如果僅僅是這樣也不是很神,似乎splay可以進行序列操作。當然,可持久化treap也有,都有split和merge了還有什么不能干?把各種標記往節點上方就行了,幾乎和splay一樣(當然基礎操作不一樣),還有,Splay不能做到可持久化(為什么?fhq大神原話:”不可以,因為勢能分析失效了!“,什么意思啊?我也不知道。。。),但是可持久化treap就可以!還有線段樹,朱(主)熹(席)樹啥的不都可以用這個搞定嗎?

  代碼沒有,相信所有人都會很容易的寫出來!這個神一般的數據結構--可持久化treap。


免責聲明!

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



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