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在插入數時,給每個...