//Treap树堆
struct Treap {
struct Node {
Node *ch[2];
int prio, val;
int cmp(int x) {
if (x == val) return -1;
return val < x;
}
//优先级比较
};
Node *root = NULL;
void insert(int x) { if (!find(x)) insert(root, x); }
void remove(int x) { if (find(x)) remove(root, x); }
bool cmp_prio(Node *a, Node *b) { return a->prio < b->prio; }
int cmp_val(Node *a, Node *b) { return a->val < b->val; }//小于往左,大于等于往右
void rotate(Node *&o, int f) {//f==0代表左旋 1代表右旋
Node *k = o->ch[f ^ 1];
o->ch[f ^ 1] = k->ch[f], k->ch[f] = o; o = k;
}
void insert(Node *&o, int x) {
if (o == NULL) {
o = new Node();
o->ch[0] = o->ch[1] = NULL; o->val = x, o->prio = rand();
}
else {
int k = o->cmp(x);
if (k == -1)
printf("已存在\n");
else {
insert(o->ch[k], x);
if (o->ch[k]->prio > o->prio)
rotate(o, k ^ 1);
}
}
}
void remove(Node *&o, int x) {
int k = o->cmp(x);
if (k == -1) {
Node *old = o;
if (o->ch[0] == NULL) o = o->ch[1], delete(old);
else if (o->ch[1] == NULL) o = o->ch[0], delete(old);
else {
int d = o->ch[0]->prio < o->ch[1]->prio;//d==0代表左子树优先级大,要右旋。。。
rotate(o, d ^ 1); remove(o->ch[d ^ 1], x);
}
}
}
int find(int x) {
Node *o = root;
while (o != NULL) {
int k = o->cmp(x);
if (k == -1)return 1;//存在
else o = o->ch[k];
}
return 0;//不存在
}
};
//*********************伸展树
struct ST {
struct Node {
Node *ch[2];
int n;//以此结点为根的树的结点数
void maintain() {
n = 1;
if (ch[0]) n += ch[0]->n;
if (ch[1]) n += ch[1]->n;
}
int get_id() {
int l = 1;
if (ch[0]) l += ch[0]->n;//l代表当前结点是第几个
return l;
}
int cmp(int x) {
int l = get_id();
if (l == x) return -1;
return l < x;
}
};
Node *root=NULL;
void rotate(Node *&o, int f) {//f==0代表左旋 1代表右旋
Node *k = o->ch[f ^ 1];
o->ch[f ^ 1] = k->ch[f], k->ch[f] = o; o = k;
o->maintain();
}
void splay(Node *&o, int k) {//找到从左数第k个元素并伸展到跟
int d1 = o->cmp(k);
if (d1 == 1) k -= o->get_id();//在右子树上
if (d1 != -1) {
Node *p = o->ch[d1];//在p树上寻找
int d2 = p->cmp(k);
if (d2 == 1) k -= p->get_id();
if (d2 != -1) {
splay(p->ch[d2], k);
if (d1 == d2) rotate(o, d1 ^ 1);
else rotate(o->ch[d1], d1);//不能用p代替ch[d1]!!!
}
rotate(o, d1 ^ 1);
}
}
Node* merge(Node* left, Node* right) {
splay(left, left->n);
left->ch[1] = right;
left->maintain();
return left;
}
void split(Node* o, int k, Node *&left, Node* &right) {
splay(o, k);
left = o;
right = o->ch[1];
left->ch[1] = NULL;
left->maintain();
}
};
树堆Treap、伸展树Splay Tree
最新推荐文章于 2021-02-20 10:39:28 发布