《題目鏈結》
學平衡樹的過程可以說是相當艱難。瀏覽blog的過程中看到大量指標版平衡樹,不擅長指標操作的我已經接近崩潰。於是,我想著一定要寫一篇非指標實現的treap的blog。
具體如下。
treap(樹堆,tree+heap)是一種強大的資料結構——每個節點除了本身鍵值(v)之外,附有乙個隨機優先順序(p),其中v滿足二叉搜尋樹性質,p滿足堆性質(下文中為大根堆),通過旋轉操作來維護性質,並使整棵樹保持平衡。
顧名思義就是可以查詢x的排名、查詢第x名的值、查詢前驅與後繼的樹。詳見標題下方題目鏈結。
struct node
;//鍵值,優先順序,(包括自身在內的)子樹大小,左右子節點。
每一種操作都是從根開始。
首先, 與插入二叉搜尋樹一樣。
給待插入節點乙個隨機的p值,為了避免重複,對生成隨機數做了一些特殊處理。
int random(void)
其次,待插入點的v到了合適的位置時,我們會發現它的p也許不符合堆性質。
這時,我們要通過旋轉操作維護堆性質。
具體操作為,以當前點為根,進行如下圖所示的旋轉。圖源網路。侵刪。
旋轉示例。圖為右旋,自繪。
旋轉後更新子樹大小。
void update(int i)
插入**。
void insert(int &i,int x)
++s[i].size;
bool t=x>s[i].v;
insert(s[i].c[t],x);
if(s[s[i].c[t]].p>s[i].p)
rotate(i,!t);
}
其實就是完全把插入的操作反過來。
待刪除的v大於當前點的v時,遞迴右子樹刪除當前點;
否則,遞迴左子樹刪除當前點。
操作完畢後更新當前點的子樹大小。
void erase(int &i,int x)
else
else
erase(s[i].c[x>s[i].v],x);
update(i);
}
int rank(int i,int x)
int xth(int i,int x)
查詢x的前驅,即查詢整個treap中比x小的最大數。
int pre(int i,int x)
和查詢前驅完全相反。
#include #include #include #include #include using namespace std;
const int maxn=100010,inf=10000010;
int n;
class treap
void insert(int &i,int x)
++s[i].size;
bool t=x>s[i].v;
insert(s[i].c[t],x);
if(s[s[i].c[t]].p>s[i].p)
rotate(i,!t);
} void erase(int &i,int x)
else
else
erase(s[i].c[x>s[i].v],x);
update(i);
} int rank(int i,int x)
int xth(int i,int x)
int pre(int i,int x)
int next(int i,int x)
{ return i ? (x
模板這種東西,尤其是**量大的,及時複習很重要。
希望我的講解可以幫助到大家吧。
謝謝閱讀。
Treap實現的名次樹
1.感覺之前邵叔叔教的做fib的那個支援刪除 其實刪除只是打標記,而且不支援插入。和查詢的排序二叉樹就是個靜態的名次樹嘛。我居然學到了這麼奇怪的資料結構。2.寫的時候坑了幾次 1 不要亂用引用,getkth裡那個引數o沒過腦子用了引用,結果把樹搞爛了,一堆ch x 賦值成null了。2 寫查詢的時候...
平衡樹模板 Treap
演算法標籤 treap 種下第一棵平衡樹 這是一道模板題。如果覺得這個題水的可以做一下4544壓行,是千古神犇花爸爸出的神犇題。您需要寫一種資料結構 可參考題目標題,但是這句話其實並沒有什麼用233 來維護一些數,其中需要提供以下操作 1.插入x數 2.刪除x數 若有多個相同的數,因只刪除乙個 3....
模板 普通平衡樹 Treap
題目描述 您需要寫一種資料結構 可參考題目標題 來維護一些數,其中需要提供以下操作 1.插入x數 2.刪除x數 若有多個相同的數,因只刪除乙個 3.查詢x數的排名 排名定義為比當前數小的數的個數 1。若有多個相同的數,因輸出最小的排名 4.查詢排名為x的數 5.求x的前驅 前驅定義為小於x,且最大的...