Treap 學習筆記

2021-09-01 12:43:42 字數 3615 閱讀 3035

tre

ap

treap

trea

p,顧名思義,就是tre

e+he

ap

tree+heap

tree+h

eap,是一種常見的平衡樹。

b st

bstbs

t性質給定一棵二叉樹,樹上的每個節點帶有乙個權值。

對於樹上的任意乙個節點,滿足:

滿足這兩條性質的二叉樹就是「二叉查詢樹」(bst

bstbs

t)。h ea

pheap

heap

性質即堆性質。

以大根堆為例,堆中的每乙個節點的權值大於子樹中任意節點的權值。

普通的bst

bstbs

t可以支援插入、刪除、檢索、求前驅/後繼等操作。

在隨機資料中,bst

bstbs

t的表現很優秀,單次操作期望時間複雜度為o(l

og2n

)o(log_2)

o(log2

​n)。

但是,如果資料呈現單調遞增的樣子,那麼bst

bstbs

t就會退化成一條鏈,單次操作o(n

)o(n)

o(n)

。為了讓一條鏈平衡,誕生了許多「平衡樹」treap就是其中一種。

滿足b st

bstbs

t性質且中序遍歷為相同序列的二叉查詢樹是不唯一的。而這些二叉查詢樹都是等價的。

我們可以在保持二叉查詢樹本質不變的情況下,改變它的形態,讓它接近一棵「平衡樹」

改變樹的形態的方法就是「旋轉」。「旋轉」又分為「左旋」「右旋」

從這張圖中,我們可以看出:

以右旋為例,將待旋轉節點a

aa旋轉至其右子樹處,然後將原來a

aa節點左兒子的右子樹全部接到現在a

aa節點的左兒子處。

void

zig(

int& p)

void

zag(

int& p)

現在,問題在於如何合理地旋轉使得樹盡可能「平衡」?

之前提到過,在資料隨機的情況下,bst

bstbs

t的期望時間複雜度為o(l

og2n

)o(log_2)

o(log2

​n)。

我們可以利用「資料隨機」的特點創造平衡條件。

對於樹上的每乙個節點,我們賦予乙個隨機出來的數值key

keyke

y,稱為「鍵值」.

插入每乙個新節點之後,我們自底向上檢查,如果key

keyke

y不符合hea

pheap

heap

性質,我們就將其旋轉,直至整棵樹同時滿足bst

bstbs

t性質和hea

pheap

heap

性質。對於刪除操作,我們可以在找到待刪除節點之後將其旋轉至葉子節點再刪除。

對於維護的資訊,可能會出現重複的權值。於是對於相同權值我們只記錄一次,同時我們記錄它的出現次數。

我們可以在一開始就加入inf

infin

f,−inf

-inf

−inf

兩個數值,避免邊界情況的處理。

於是,我們就可以在期望o(l

og2n

)o(log_2)

o(log2

​n)的時間內實現檢索、插入、刪除、求前驅/後繼。

以模板(普通平衡樹)為例,給出tre

ap

treap

trea

p的**:

#include

#include

#include

#include

using

namespace std;

const

int inf =

0x3f3f3f3f

, maxn =

100010

;int n, tot, root =1;

struct treap tree[maxn]

;void

push_up

(int u)

intnew

(int val)

void

build()

void

zig(

int& p)

void

zag(

int& p)

void

insert

(int

& p,

int val)

if(val == tree[p]

.val)

if(val < tree[p]

.val)

else

push_up

(p);

}void

remove

(int

& p,

int val)

if(tree[p]

.l || tree[p]

.r)else p =0;

return;}

if(val < tree[p]

.val)

remove

(tree[p]

.l, val)

;else

remove

(tree[p]

.r, val)

;push_up

(p);

}int

get_rank

(int p,

int val)

intget_val

(int p,

int rank)

intpre

(int val)

break;}

if(tree[p]

.val < val && tree[p]

.val > tree[ret]

.val) ret = p;

if(val < tree[p]

.val) p = tree[p]

.l;else p = tree[p]

.r;}

return tree[ret]

.val;

}int

next

(int val)

break;}

if(tree[p]

.val > val && tree[p]

.val < tree[ret]

.val) ret = p;

if(val < tree[p]

.val) p = tree[p]

.l;else p = tree[p]

.r;}

return tree[ret]

.val;

}int

main()

return0;

}

學習筆記 Treap

學習treap之前先學的splay,然後發現treap真是太簡單了,greatwall1995神犇的意見要聽啊 bst的缺陷是因為人為搞單調資料才爆的,隨機資料還是logn的時間,treap的思想也基於此,給每個新增的點賦乙個隨機優先值,然後整個樹關於優先值是乙個堆。clrs上要求讀者證明插入節點後...

Treap學習筆記

開乙個坑,學一學treap專題 mark乙個習題集 帶旋轉treap模板 struct treap tr 100005 int n,size,root,ans void update int k 更新結點資訊 旋轉 void rturn int k void lturn int k void ins...

Treap 學習筆記

平衡樹就是一種可以在log的時間複雜度內完成資料的插入,刪除,查詢第k大,查詢排名,查詢前驅後繼以及其他許多操作的資料結構。treap是一種比較好寫,常數比較小,可以實現平衡樹基本操作的一種平衡樹。treap的平衡是基於隨機化。是將堆與二叉查詢樹結合起來所得到的資料結構。treap在插入數時,給每個...