Treap樹堆 是一種 隨機平衡二叉樹。
相對於正正規規的AVL樹,倒是靈活了許多。
Treap 也有旋轉模式,但是隻有單選轉,而且Treap的旋轉,怎麼旋轉,該不該旋轉完全是隨機化的,這樣子在大大減少了編碼量的同時,相對也把效率給提了上去。在最差情況下也比最差情況下的樸素 BST 好
代碼參考 《Data Structure and Algorithm Analysis in C》
結構體部分:
typedef struct Treap * Node;
Node root = 0; //保存根節點
Node NulNode = 0; //傳說中的標記節點,不使用NULL是因爲怕出錯,而且代碼寫起來較方便
//可以理解爲代替空指針防止出錯的自定義指針
struct Treap
{
Node left, right; //子節點
int key; //值,可自定義
int priority; //優先級,隨機生成的一個數,後面會用到。
};
左右旋轉
Node L_Rotate(Node K2)
{
Node K1 = K2 -> left;
K2 -> left = K1 -> right;
K1 -> right = K2;
return K1;
}
Node R_Rotate(Node K2)
{
Node K1 = K2 -> right;
K2 -> right = K1 -> left;
K1 -> left = K2;
return K1;
}
插入其實也不難,記得每次執行插入後旋轉一次
Node insert(Node T,int key)
{
// 採用遞歸寫法
int num = rand() % 10086383; //產生一個隨機數
if(T == NulNode) //如果樹爲空,則新建
{
T = new Treap();
T -> key = key;
T -> priority = num;
T -> left = T -> right = NulNode; //初始化
return T;
}
else
{
if (key > T->key) //插入值比當前大,往右。
{
T->right = insert(T->right , key); //注意! T->right = insert(T->right,key) 左邊right不能丟
if(T -> left -> priority < T -> right -> priority)
T = L_Rotate(T); //插入後旋轉
}
else if (key < T->key)
{
T->left = insert(T->left , key);
if(T -> left -> priority > T -> right -> priority)
T = R_Rotate(T);
}
}
return T;
}
刪除略有些麻煩。
Node Remove(Node T , int key)
{
if(T!=NulNode) //如果不爲空
{
if (key < T ->key)
T->left = Remove(T->left,key);
else if (key > T->key)
T->right = Remove(T->right,key);
else
{
if(T->left->priority < T -> right -> priority)
T = L_Rotate(T);
else
T = R_Rotate(T); //調整到所求點爲葉節點
if(T != NulNode)
T = Remove(T , key);
else
{
delete T -> left; //要刪的節點 仍有左右子樹NulNode,
//爲了返回值時,好處理,所以用旋轉把key所在地方變爲NulNode的子節點後刪除。
T->left = NulNode;
}
}
}
return T;
}