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;
}