3. treap的操作
同其他樹形結構一樣,treap的基本操作有:查詢,插入,刪除等。
3.1 查詢
同其他二叉樹一樣,treap的查詢過程就是二分查詢的過程,複雜度為o(lg n)。
3.2 插入
在treap 中插入元素,與在bst 中插入方法相似。首先找到合適的插入位置,然後建立新的節點,儲存元素。但是要注意新的節點會有乙個優先順序屬性,該值可能會破壞堆序,因此我們要根據需要進行恰當的旋轉。具體方法如下:
1. 從根節點開始插入;
2. 如果要插入的值小於等於當前節點的值,在當前節點的左子樹中插入,插入後如果左子節點的優先順序小於當前節點的優先順序,對當前節點進行右旋;
3. 如果要插入的值大於當前節點的值,在當前節點的右子樹中插入,插入後如果右子節點的優先順序小於當前節點的優先順序,對當前節點進行左旋;
4. 如果當前節點為空節點,在此建立新的節點,該節點的值為要插入的值,左右子樹為空,插入成功。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
treap_node *root;
void
treap_insert(treap_node *&p,
int
value)
//節點指標一定要傳遞引用 p為要插入樹的根節點
else
if
(value <= p->value)
else
}
3.3:刪除
跟普通的二叉查詢樹一樣,刪除結點存在三種情況。
①:葉子結點
跟普通查詢樹一樣,直接釋放本節點即可。
②:單孩子結點
跟普通查詢樹一樣操作。
③:滿孩子結點
其實在treap中刪除滿孩子結點有兩種方式。
第一種:跟普通的二叉查詢樹一樣,找到「右子樹」的最左結點(15),拷貝元素的值,但不拷貝元素的優先順序,然後在右子樹中
刪除「結點15」即可,最終效果如下圖。
第二種:將」結點下旋「,直到該節點不是」滿孩子的情況「,該賦null的賦null,該將孩子結點頂上的就頂上,如下圖:
當然從理論上來說,第二種刪除方法更合理,這裡我寫的就是第二種情況的**。
1#region 刪除當前樹中的節點
2///
3///
刪除當前樹中的節點
4///
5///
6///
7public
void
remove(k key, v value)811
#endregion
1213
#region 刪除當前樹中的節點
14///
15///
刪除當前樹中的節點
16///
17///
18///
19///
20public treapnoderemove(k key, v value, treapnodetree)
2130
//右子樹
31if (key.compareto(tree.key) > 0)32
35/*
相等的情況
*/36
if (key.compareto(tree.key) == 0)37
44else
4554
else
5559
60//
繼續旋轉
61 tree =remove(key, value, tree);62}
63else
6472}73
}7475return
tree;76}
77#endregion
Treap實現的名次樹
1.感覺之前邵叔叔教的做fib的那個支援刪除 其實刪除只是打標記,而且不支援插入。和查詢的排序二叉樹就是個靜態的名次樹嘛。我居然學到了這麼奇怪的資料結構。2.寫的時候坑了幾次 1 不要亂用引用,getkth裡那個引數o沒過腦子用了引用,結果把樹搞爛了,一堆ch x 賦值成null了。2 寫查詢的時候...
線段樹套Treap
題目為bzoj1901.單點修改區間第k大,如果卡記憶體你要怎麼辦 hq說線段樹套平衡樹比樹狀陣列套線段樹好得多 所以我就寫了 然後就寫了 n log 3n 在zju上t掉了qaq 卡記憶體還卡時間真是有夠過分 其實就是外層線段樹存一下根然後按照正常的treap寫就好了,但是有乙個問題就是treap...
平衡樹之Treap
乙個集合支援快速插入 刪除乙個數字。支援快速查詢乙個數字在所有已插入數字中的排名。支援刪除大小在某乙個區間內的數字。動態維護乙個數列。可以在數列的任何位置插入刪除,求區間和,min,max,進行區間翻轉 這就需要用到二叉查詢樹 binary search tree 性質 這是一棵二叉樹。對於任意乙個...