Treap还是比较好写的,但是要加入动态顺序统计和parent指针就稍微有些麻烦了。一个重要的经验是采用哨兵(本例中是nullnode),这样会带来很大方便的。
//
结点类型
typedef
struct
node
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
int key, pri, size; //关键字,权值,统计量
node *left, *right, *parent; //左孩子、右孩子、父结点
//初始化一个空结点
node()
: pri(INT_MAX), left(NULL), right(NULL), parent(NULL), size(1)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{}
//用制定的参数初始化
node(int k, node *l, node *r, node *p, int pr)
: key(k), left(l), right(r), parent(p), pri(pr), size(1)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{}
}
*
nodeptr;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
//
Treap类
class
Treap
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
...
{
private:
nodeptr root;
nodeptr nullnode;
//左旋
inline void rotate_left(nodeptr &t)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
nodeptr p = t -> right;
p -> parent = t -> parent;
t -> right = p -> left;
p -> left -> parent = t;
p -> left = t;
t -> parent = p;
p -> size = t -> size;
t -> size = t -> left -> size + t -> right -> size + 1;
t = p;
}
//右旋
inline void rotate_right(nodeptr &t)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
nodeptr p = t -> left;
p -> parent = t -> parent;
t -> left = p -> right;
p -> right -> parent = t;
p -> right = t;
t -> parent = p;
p -> size = t -> size;
t -> size = t -> left -> size + t -> right -> size + 1;
t = p;
}
//向t处插入值为x的结点
inline void insert(int x, nodeptr &t, nodeptr pi)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (t == nullnode)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
srand(static_cast<unsigned long>(time(NULL)));
//下面这句注意:
//VC 2005下,应为rand()*rand()
//g++下,应为rand()
t = new node(x, nullnode, nullnode, pi, rand());
//向上更新
nodeptr tmp = t;
while (tmp -> parent != nullnode)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
tmp = tmp -> parent;
tmp -> size++;
}
return;
}
if (x < t -> key)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
insert(x, t -> left, t);
if (t -> left -> pri < t -> pri)
rotate_right(t);
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
insert(x, t -> right, t);
if (t -> right -> pri < t -> pri)
rotate_left(t);
}
}
inline void remove(int x, nodeptr &t)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (t == nullnode)
return;
if (x < t -> key)
remove(x, t -> left);
else if (x > t -> key)
remove(x, t -> right);
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
//以下用来处理有相同key的结点
bool skip = false;
if (t -> left != nullnode && t -> key == t -> left -> key)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
remove (x, t -> left);
skip = true;
}
else if (t -> right != nullnode && t -> key == t -> right -> key)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
remove (x, t -> right);
skip = true;
}
//以下是正常的删除准备
else if (t -> left -> pri < t -> right -> pri)
rotate_right(t);
else
rotate_left(t);
//没有相同结点时直接删除
if (!skip)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (t != nullnode)
remove(x, t);
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
delete t -> left;
t -> left = nullnode;
}
}
}
}
inline void makeEmpty(nodeptr &t)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (t != nullnode)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
makeEmpty (t -> left);
makeEmpty (t -> right);
delete t;
}
t = nullnode;
}
inline void travel(nodeptr &t)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (t != nullnode)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
travel(t -> left);
//请改为相关操作
cout << t -> key << endl;
travel (t -> right);
}
}
//返回以current为根的树最小值
inline nodeptr min(nodeptr current)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
while (current -> left != nullnode)
current = current->left;
return current;
}
//返回以current为根的树最大值
inline nodeptr max(nodeptr current)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
while (current -> right != nullnode)
current = current -> right;
return current;
}
//返回以x为根,第i大的元素的值
inline nodeptr select(nodeptr x, int i)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
int r = x -> left -> size + 1;
if (i == r)
return x;
else if (i < r)
return select(x -> left, i);
else
return select(x -> right, i - r);
}
public:
Treap()
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
nullnode = new node; //哨兵结点
nullnode -> left = nullnode -> right = nullnode -> parent = nullnode;
nullnode -> size = 0;
root = nullnode; //根为空
}
~Treap()
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
makeEmpty();
delete nullnode;
}
//返回最小元素
inline nodeptr min()
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (isEmpty())
return NULL;
return min(root);
}
//返回最大元素
inline nodeptr max()
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (isEmpty())
return NULL;
return max(root);
}
//返回是否空
inline bool isEmpty()
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
return (root == nullnode);
}
//插入x
inline void insert(int x)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
insert(x, root, nullnode);
}
//删除值为x的结点
inline void remove(int x)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
remove(x, root);
}
//清空
inline void makeEmpty()
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
makeEmpty(root);
}
//遍历
inline void travel()
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (!isEmpty())
travel(root);
}
//查找
//如果存在,返回指向这个结点的指针,否则返回NULL
inline nodeptr find(int x)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
nodeptr current = root;
nullnode -> key = x;
while(1)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (x < current -> key)
current = current -> left;
else if (x > current -> key)
current = current -> right;
else if (current != nullnode)
return current;
else
return NULL;
}
}
//返回后继
inline nodeptr succ(nodeptr current)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (current == NULL)
return NULL;
if (current -> right != nullnode)
return min(current -> right);
nodeptr y = current -> parent;
while (y != nullnode && current == y -> right)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
current = y;
y = y -> parent;
}
return y;
}
inline nodeptr succ(int x)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
return succ(find(x));
}
//返回前驱
inline nodeptr pred(nodeptr current)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (current == NULL)
return NULL;
if (current -> left != nullnode)
return max(current -> left);
nodeptr y = current -> parent;
while (y != nullnode && current == y -> left)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
current = y;
y = y -> parent;
}
return y;
}
inline nodeptr pred(int x)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
return pred(find(x));
}
inline nodeptr select(int i)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
return select(root, i);
}
//返回x在树中的位置
inline int rank(nodeptr x)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
int r = x -> left -> size + 1;
nodeptr y = x;
while (y != root)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
if (y == y -> parent -> right)
r += y -> parent -> left -> size +1;
y = y -> parent;
}
return r;
}
}
;