中級資料結構學習筆記 一 Treap

2021-06-27 05:42:56 字數 3589 閱讀 5275

顧名思義,treap=tree+heap(平衡二叉樹+堆)。treap是一種在鍵值上滿足平衡二叉樹性質、在優先順序上滿足堆性質的資料結構。

我們都知道平衡二叉樹(以下簡稱bst),在一棵bst中,乙個結點的左子樹中的元素鍵值均小於該結點的鍵值,右子樹中的元素鍵值均大於該結點的鍵值,圖(1)就是一棵bst。通過bst,我們可以用類似於二分查詢的方法快速地在樹中進行查詢操作。

但是bst也有缺點。最好情況下,一棵有n個結點的bst的深度為logn,但是實際上bst的深度還取決於其根結點的鍵值,根結點的鍵值如果過大或者過小,bst的深度就會增大很多,甚至於出現退化成煉表的情況,如圖(2),這時bst的查詢複雜度為o(n)。

為了避免這種情況的發生,讓樹的深度盡量小,我們需要在保證維護這棵樹具備bst的性質的前提下,對其根結點進行調整,於是treap出現了。treap就是在bst的基礎上引入了乙個類似於heap中的優先順序,treap在具備bst平衡的前提下,還具備乙個heap的性質,即乙個結點的優先順序比其子樹中的結點的優先順序都要大,在改變一棵treap的同時,需要對結點位置進行調整,維護treap的性質,而每個結點的優先順序都是隨機數,這樣就保證了treap的深度盡量小,treap是一種隨機樹。如圖(3)就是一棵treap。

在競賽中,為了方便除錯,減少錯誤的發生概率,推薦使用陣列版treap。以下是一棵陣列版的treap樹的實現,適用於大多數的題目,對於不同的題目需要根據實際情況,對模板進行適當調整。

1、treap結點的定義

乙個treap的結點包含下列資訊:

1、左右兒子結點指標 l,r

2、結點鍵值 v (為了擴大模板的適用範圍,鍵值用結構體info代替,info需要進行''、'=='的運算子過載)

3、結點優先順序 rnd

4、該結點和其子樹中的結點個數 s

5、該結點對應的相同鍵值元素個數 cnt

另外,還要維護乙個數字ncount表示已經占用結構體陣列的大小,和乙個當前根節點指標root。

**:

struct node

tree[maxn];

int ncount=0;

int ans;

int root=0;

2、treap的結點插入操作

如圖(4),我們要在鍵值為10的根節點x下插入鍵值為13的結點a,操作為insert(x,a)。插入操作時需要維護treap的平衡性質,如果x是個空指標,那麼a就充當x,如果a的鍵值比x大,向x的右子樹插入,如果a的鍵值比x小,插入x的左子樹,否則標記本結點的元素個數+1。

**:

void insert(int &o,info x) //在根節點為o的樹中插入鍵值為x的結點,若存在鍵值為x的結點,那麼增加該結點對應數字個數

tree[o].s++;

if(xtree[lc].rnd) //注意維護堆的性質

rotater(o);

}else if(x>tree[o].v) //x比根結點鍵值大,往右子樹插,下面操作類似上面

else //x和根節點鍵值一樣,那麼增加根節點對數字個數

tree[o].cnt++;

}

3、旋轉操作

如圖(5)是一棵treap樹的旋轉操作,從左到右是右旋結點b(rotater(b)),從右到左是左旋結點b(rotatl(b))。一般的,插入結點或刪除結點後,為了維護treap的堆性質,需要進行旋轉操作,旋轉操作需要同時保證treap的平衡性質。

void rotater(int &o) //右旋結點o

void rotatel(int &o) //左旋結點o

4、刪除操作

刪除乙個結點時,同樣需要維護treap的平衡樹和堆的性質。若該結點只有乙個兒子,那麼刪除該結點後,讓它的兒子變動到該結點的位置即可。但如果該結點有兩個兒子,則需要分類討論:1、右兒子優先值比左兒子大,則需要先右旋結點o,再刪除結點o。2、右兒子優先值比左兒子小,則需要先左旋結點o,再刪除結點o。

**(lc代表o的左兒子,rc代表o的右兒子,lc和rc在**的巨集定義部分中):

void del(int &o,info x) //在根節點為o的樹中刪除《乙個》鍵值為x的點

7、維護結點資訊

維護結點資訊很簡單,只需要更新結點的s值即可。樹的結構發生變化時需要維護結點資訊。

void update(int o) //維護結點o

#include #include #include #include #include #include #include #include #define maxn 250010

#define lc (tree[o].l)

#define rc (tree[o].r)

using namespace std;

maphash;

mapfenshu;

mapname;

int tot=0; //已經加入玩家個數

struct info

bool operator==(const info &b)const

}; struct node

tree[maxn];

int ncount=0;

int ans;

int root=0;

void update(int o) //維護結點o

void rotater(int &o) //右旋結點o

void rotatel(int &o) //左旋結點o

void insert(int &o,info x) //在根節點為o的樹中插入鍵值為x的結點,若存在鍵值為x的結點,那麼增加該結點對應數字個數

tree[o].s++;

if(xtree[lc].rnd) //注意維護堆的性質

rotater(o);

}else if(x>tree[o].v) //x比根結點鍵值大,往右子樹插,下面操作類似上面

else //x和根節點鍵值一樣,那麼增加根節點對數字個數

tree[o].cnt++;}

void del(int &o,info x) //在根節點為o的樹中刪除《乙個》鍵值為x的點

int main()

else

}else

for(int i=ranker;i<=tot&&i<=ranker+9;i++)

{if(i!=ranker) cout<

cout<



資料結構學習筆記 一

1 資料結構 眾所周知,電腦程式是對資訊進行的加工處理.在一般情況下,這些資訊並不是沒有組織,資訊之間往往具有重要的結構關係,這就是資料結構的內容.設有乙個 號碼薄,它記錄了n個人的名字和其相應的 號碼,假定按如下形式安排 a1,b1 a2,b2 an,bn 其中ai,bi i 1,2 n 分別表示...

資料結構學習筆記 一

資料結構研究非數值計算的程式設計問題中的操作物件,以及他們之間關係和操作 程式設計 資料結構 演算法 資料結構 資料 資料的構成方式 資料,能夠由計算機操作的物件,能夠由計算機識別,並輸入給計算機處理的符號集合。兩個特徵 可以輸入到計算機中,能被電腦程式處理 資料,資料元素,資料項,資料物件,資料結...

資料結構學習筆記(一)

資料結構是一門研究非數值計算的程式設計問題中計算機的操作物件以及它們之間的關係和操作的學科。通常有下列四類基本結構 1 集合 2 線性結構 3 樹形結構 4 圖狀結構或網狀結構 資料結構的形式定義為 data structure d,s 其中d是資料元素的有限集,s是d上關係的有限集。結構定義中的 ...