1. 概述
同splay tree一樣,treap也是乙個平衡二叉樹,不過treap會記錄乙個額外的資料,即優先順序。treap在以關鍵碼構成二叉搜尋樹的同時,還按優先順序來滿足堆的性質。因而,treap=tree+heap。這裡需要注意的是,treap並不是二叉堆,二叉堆必須是完全二叉樹,而treap可以並不一定是。
2. treap基本操作
為了使treap 中的節點同時滿足bst性質和最小堆性質,不可避免地要對其結構進行調整,調整方式被稱為旋轉。在維護treap 的過程中,只有兩種旋轉,分別是左旋轉(簡稱左旋)和右旋轉(簡稱右旋)。
左旋乙個子樹,會把它的根節點旋轉到根的左子樹位置,同時根節點的右子節點成為子樹的根;右旋乙個子樹,會把它的根節點旋轉到根的右子樹位置,同時根節點的左子節點成為子樹的根。
struct treap_node
;void treap_left_rotate(treap_node *&a) //左旋 節點指標一定要傳遞引用
void treap_right_rotate(treap_node *&a) //右旋 節點指標一定要傳遞引用
3. treap的操作同其他樹形結構一樣,treap的基本操作有:查詢,插入,刪除等。
3.1 查詢
同其他二叉樹一樣,treap的查詢過程就是二分查詢的過程,複雜度為o(lg n)。
3.2 插入
在treap 中插入元素,與在bst 中插入方法相似。首先找到合適的插入位置,然後建立新的節點,儲存元素。但是要注意新的節點會有乙個優先順序屬性,該值可能會破壞堆序,因此我們要根據需要進行恰當的旋轉。具體方法如下:
1. 從根節點開始插入;
2. 如果要插入的值小於等於當前節點的值,在當前節點的左子樹中插入,插入後如果左子節點的優先順序小於當前節點的優先順序,對當前節點進行右旋;
3. 如果要插入的值大於當前節點的值,在當前節點的右子樹中插入,插入後如果右子節點的優先順序小於當前節點的優先順序,對當前節點進行左旋;
4. 如果當前節點為空節點,在此建立新的節點,該節點的值為要插入的值,左右子樹為空,插入成功。
treap_node *root;
void treap_insert(treap_node *&p,int value) //節點指標一定要傳遞引用
else if (value <= p->value)
else
}
3.3 刪除與bst 一樣,在treap 中刪除元素要考慮多種情況。我們可以按照在bst 中刪除元素同樣的方法來刪除treap 中的元素,即用它的後繼(或前驅)節點的值代替它,然後刪除它的後繼(或前驅)節點。
上述方法期望時間複雜度為o(logn),但是這種方法並沒有充分利用treap 已有的隨機性質,而是重新得隨機選取代替節點。我們給出一種更為通用的刪除方法,這種方法是基於旋轉調整的。首先要在treap 樹中找到待刪除節點的位置,然後分情況討論:
情況一,該節點為葉節點或鏈節點,則該節點是可以直接刪除的節點。若該節點有非空子節點,用非空子節點代替該節點的,否則用空節點代替該節點,然後刪除該節點。
情況二,該節點有兩個非空子節點。我們的策略是通過旋轉,使該節點變為可以直接刪除的節點。如果該節點的左子節點的優先順序小於右子節點的優先順序,右旋該節點,使該節點降為右子樹的根節點,然後訪問右子樹的根節點,繼續討論;反之,左旋該節點,使該節點降為左子樹的根節點,然後訪問左子樹的根節點,這樣繼續下去,直到變成可以直接刪除的節點。
bst_node *root;
void treap_delete(treap_node *&p,int *value) //節點指標要傳遞引用
else //情況二
else //左子節點修正值較小,左旋
}} else if (value < p->value)
treap_delete(p->left,r); //在左子樹查詢要刪除的節點
else
treap_delete(p->right,r); //在右子樹查詢要刪除的節點
}
4. treap應用treap可以解決splay tree可以解決的所有問題,具體參見另一篇博文:《資料結構之伸展樹》
可以這樣定義結構體:
struct treap_node
//返回左子樹的節點個數
inline int rsize() //返回右子樹的節點個數
};
5. 總結treap 作為一種簡潔高效的有序資料結構,在電腦科學和技術應用中有著重要的地位。它可以用來實現集合、多重集合、字典等容器型資料結構,也可以用來設計動態統計資料結構。
6. 參考資料
(1)treap:
更多關於資料結構和演算法的介紹,請檢視:資料結構與演算法彙總
資料結構 Treap
前兩天看了byvoid大神寫的treap的 中幾乎給出了所有的 不過最後一部提到了乙個優化,就是對於重複的元素採用在同乙個節點中記錄乙個weight來記錄者個元素使用了多少次的寫法,以及查詢第k個數的功能的實現,我試著寫了乙個,表示樹旋轉之後需要重新設定size有一點點煩。因為找不到合適的題目去測試...
模板 資料結構 Treap
還有人把treap叫做樹堆的,但是常用名還是叫做treap的比較多。不進行任何封裝的,帶求和操作的,乙個節點存放多個元素的最普通的treap。includeusing namespace std typedef long long ll define ls ch id 0 define rs ch ...
演算法 資料結構 Treap
treap 完整版 struct treap void pushup int u void rotate int u,int d void inserthelp int u,ll v,ll c else if v val u else pushup u void removehelp int u,l...