樹堆

三層的樹堆
樹堆（Treap），是計算機科學中術語。是有一個隨機附加域滿足堆的性質的二叉搜索樹，其結構相當於以隨機數據插入的二叉搜索樹。其基本操作的期望時間複雜度為。相對於其他的平衡二叉搜索樹，Treap的特點是實現簡單，且能基本實現隨機平衡的結構。屬於弱平衡樹。

**介紹**
Treap一詞由Tree和Heap二詞合成而來。其本身是一棵二叉搜索樹，它的左子樹和右子樹也分別是一個Treap，和一般的二叉搜索樹不同的是，Treap為每個節點記錄優先級。Treap在以關鍵碼構成二叉搜索樹的同時，其節點優先級還滿足堆的性質。Treap維護堆性質的方法用到了旋轉，且只需要進行兩種旋轉操作，因此編程複雜度較Splay要小一些。

**插入**
給節點隨機分配一個優先級，先和二叉搜索樹的插入一樣，先把要插入的點插入到一個葉子上，然後跟維護堆一樣進行以下操作：
# 如果當前節點的優先級比父節點大就進行2. 或3. 的操作
# 如果當前節點是父節點的左子葉就右旋
# 如果當前節點是父節點的右子葉就左旋。
由於旋轉是的，最多進行h次（h是樹的高度），插入的複雜度是的，在期望情況下，所以它的期望複雜度是。

**刪除**
因為Treap滿足堆性質，所以只需要把要刪除的節點旋轉到葉節點上，然後直接刪除就可以了。具體的方法就是每次找到優先級最大的子葉，向與其相反的方向旋轉，直到那個節點被旋轉到了葉節點，然後直接刪除。
刪除最多進行次旋轉，期望複雜度是。

**查找**
和一般的二叉搜索樹一樣，但是由於Treap的隨機化結構，Treap中查找的期望複雜度是。

**算法分析**
二叉搜索樹有一個特性，就是每個子樹的形態在優先級唯一確定的情況下都是唯一的，不受其他因素影響，也就是說，左子樹的形態與樹中大於根節點的值無關，右子樹亦然。這是因為Treap滿足堆的性質，Treap的根節點是優先級最大的那個節點，考慮它的左子樹，樹根也是子樹裡面最大的一點，右子樹亦然。所以Treap相當於先把所有節點按照優先級排序，然後插入，實質上就相當於以隨機順序建立的二叉搜索樹，只不過它並不需要一次讀入所有數據，可以一個一個地插入。而當這個隨機順序確定的時候，這個樹是唯一的。因此在給定優先級的情況下，只要是用符合要求的操作，通過任何方式得出的Treap都是一樣的，所以不改變優先級的情況下，特殊的操作不會造成Treap結構的退化。而改變優先級可能會使Treap變得不夠隨機以致退化。
Treap的其它操作的期望複雜度同樣是。

**參考程序**

**Pascal版本**
(    Project: Amber Standard Sources Library ASSL
Author: Amber
Title: Treap
Category: Data Structure
Version: v1.0
Remark: XXXXXXXX
Tested Problems: N/A
Date: 2006-11-16
*)
program ASSL_Treap(Input, Output);
const
Infinity = 65535;
type
TIndex = Longint;
TKey = Longint;
TPriority = Word;
PTreapNode = ^TTreapNode;
TTreapNode = record
Left, Right: PTreapNode;
Priority: TPriority;
Key: TKey;
end;
var
NullNode: PTreapNode;

procedure Initalize;
begin
if NullNode = nil then
begin
New(NullNode);
NullNode^.Left := NullNode;
NullNode^.Right := NullNode;
NullNode^.Priority := Infinity;
end;
end;

function FindMax(T: PTreapNode): PTreapNode;
begin
if T  NullNode then
while T^.Right  NullNode do
T := T^.Right;
Result := T;
end;

function FindMin(T: PTreapNode): PTreapNode;
begin
if T  NullNode then
while T^.Left  NullNode do
T := T^.Left;
Result := T;
end;

function Find(T: PTreapNode; Key: TKey): PTreapNode;
begin
while T  NullNode do
if Key  T^.Key then
T := T^.Right
else
Break;
Result := T;
end;

function LeftRotate(T: PTreapNode): PTreapNode;
begin
Result := T^.Left;
T^.Left := Result^.Right;
Result^.Right := T;
end;

function RightRotate(T: PTreapNode): PTreapNode;
begin
Result := T^.Right;
T^.Right := Result^.Left;
Result^.Left := T;
end;

function InsertNode(Key: TKey; T: PTreapNode): PTreapNode;
begin
if T = NullNode then
begin
New(T);
T^.Left := NullNode;
T^.Right := NullNode;
T^.Key := Key;
T^.Priority := Random(65535);
end
else if Key  T^.Key then
begin
T^.Right := InsertNode(Key, T^.Right);
if T^.Right^.Priority  NullNode then
if Key  T^.Key then
T^.Right := DeleteNode(Key, T^.Right)
else
begin
if T^.Left^.Priority  NullNode then
T := DeleteNode(Key, T)
else //RightRotate
begin
Dispose(T^.Left);
T^.Left := NullNode;
end;
end;
Result := T;
end;

procedure Main;
begin
Initalize;
end;
begin
Main;
end;

**C++版本**
#include 
#include 
#include 
#define MAX 100
using namespace std;
typedef struct
{
	int l,r,key,fix;
} node;
class treap
{
public:
	node pMAX;
	int size,root;
	treap()
	{
		srand(time(0));
		size=-1;
		root=-1;
	}
	void rot_l(int &x)
	{
		int y=px.r;
		px.r=py.l;
		py.l=x;
		x=y;
	}
	void rot_r(int &x)
	{
		int y=px.l;
		px.l=py.r;
		py.r=x;
		x=y;
	}
	void insert(int &k,int tkey)
	{
		if (k==-1)
		{
			k=++size;
			pk.l=pk.r=-1;
			pk.key=tkey;
			pk.fix=rand();
		}
		else if (tkeypk.fix)
				rot_r(k);
		}
		else
		{
			insert(pk.r,tkey);
			if (p pk.r .fix>pk.fix)
				rot_l(k);
		}
	}
	void remove(int &k,int tkey)
	{
		if (k==-1) return;
		if (tkeypk.key)
			remove(pk.r,tkey);
		else
		{
			if (pk.l==-1 && pk.r==-1)
				k=-1;
			else if (pk.l==-1)
				k=pk.r;
			else if (pk.r==-1)
				k=pk.l;
			else if (p pk.l .fix = 1; i--)
		T.insert(T.root,i);
	T.print(T.root);
	for (i = 3; i >= 1; i--)
	{
		cout 

**與其他結構的比較**
AVL樹
*伸展樹（Splay Tree）
*線段樹
*紅黑樹
*Size Balanced Tree

**外部鏈接**
 一個Treap的演示 date=20210225091757 - Randomized Search Trees(pdf)，有對Treap和它的加權形式的詳盡介紹以及複雜度的嚴格證明- nocow.cn - Treap