Treap

 Treap还是比较好写的,但是要加入动态顺序统计和parent指针就稍微有些麻烦了。一个重要的经验是采用哨兵(本例中是nullnode),这样会带来很大方便的。

 

// 结点类型
typedef  struct  node
{
    
int key, pri, size;    //关键字,权值,统计量
    node *left, *right, *parent;    //左孩子、右孩子、父结点
    
//初始化一个空结点
    node()
        : pri(INT_MAX), left(NULL), right(NULL), parent(NULL), size(
1)
    
{}
    
//用制定的参数初始化
    node(int k, node *l, node *r, node *p, int pr)
        : key(k), left(l), right(r), parent(p), pri(pr), size(
1)
    
{}
}
* nodeptr;

// Treap类
class  Treap
{
private:
    nodeptr root;
    nodeptr nullnode;
    
//左旋
    inline void rotate_left(nodeptr &t)
    
{
        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)
    
{
        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)
    
{
        
if (t == nullnode)
        
{
            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)
            
{
                tmp 
= tmp -> parent;
                tmp 
-> size++;
            }

            
return;
        }

        
if (x < t -> key)
        
{
            insert(x, t 
-> left, t);
            
if (t -> left -> pri < t -> pri)
                rotate_right(t);
        }

        
else
        
{
            insert(x, t 
-> right, t);
            
if (t -> right -> pri < t -> pri)
                rotate_left(t);
        }

    }

    inline 
void remove(int x, nodeptr &t)
    
{
        
if (t == nullnode)
            
return;
        
if (x < t -> key)
            remove(x, t 
-> left);
        
else if (x > t -> key)
            remove(x, t 
-> right);
        
else
        
{
            
//以下用来处理有相同key的结点
            bool skip = false;
            
if (t -> left != nullnode && t -> key == t -> left -> key)
            
{
                remove (x, t 
-> left);
                skip 
= true;
            }

            
else if (t -> right != nullnode && t -> key == t -> right -> key)
            
{
                remove (x, t 
-> right);
                skip 
= true;
            }

            
//以下是正常的删除准备
            else if (t -> left -> pri < t -> right -> pri)
                rotate_right(t);
            
else
                rotate_left(t);
            
//没有相同结点时直接删除
            if (!skip)
            
{
                
if (t != nullnode)
                    remove(x, t);
                
else
                
{
                    delete t 
-> left;
                    t 
-> left = nullnode;
                }

            }

        }

    }

    inline 
void makeEmpty(nodeptr &t)
    
{
        
if (t != nullnode)
        
{
            makeEmpty (t 
-> left);
            makeEmpty (t 
-> right);
            delete t;
        }

        t 
= nullnode;
    }

    inline 
void travel(nodeptr &t)
    
{
        
if (t != nullnode)
        
{
            travel(t 
-> left);
            
//请改为相关操作
            cout << t -> key << endl;
            travel (t 
-> right);
        }

    }

    
//返回以current为根的树最小值
    inline nodeptr min(nodeptr current)
    
{
        
while (current -> left != nullnode)
            current 
= current->left;
        
return current;
    }

    
//返回以current为根的树最大值
    inline nodeptr max(nodeptr current)
    
{
        
while (current -> right != nullnode)
            current 
= current -> right;
        
return current;
    }

    
//返回以x为根,第i大的元素的值
    inline nodeptr select(nodeptr x, int i)
    
{
        
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()
    
{
        nullnode 
= new node;    //哨兵结点
        nullnode -> left = nullnode -> right = nullnode -> parent = nullnode;
        nullnode 
-> size = 0;
        root 
= nullnode;    //根为空
    }

    
~Treap()
    
{
        makeEmpty();
        delete nullnode;
    }

    
//返回最小元素
    inline nodeptr min()
    
{
        
if (isEmpty())
            
return NULL;
        
return min(root);
    }

    
//返回最大元素
    inline nodeptr max()
    
{
        
if (isEmpty())
            
return NULL;
        
return max(root);
    }

    
//返回是否空
    inline bool isEmpty()
    
{
        
return (root == nullnode);
    }

    
//插入x
    inline void insert(int x)
    
{
        insert(x, root, nullnode);
    }

    
//删除值为x的结点
    inline void remove(int x)
    
{
        remove(x, root);
    }

    
//清空
    inline void makeEmpty()
    
{
        makeEmpty(root);
    }

    
//遍历
    inline void travel()
    
{
        
if (!isEmpty())
            travel(root);
    }

    
//查找
    
//如果存在,返回指向这个结点的指针,否则返回NULL
    inline nodeptr find(int x)
    
{
        nodeptr current 
= root;
        nullnode 
-> key = x;
        
while(1)
        
{
            
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)
    
{
        
if (current == NULL)
            
return NULL;
        
if (current -> right != nullnode)
            
return min(current -> right);
        nodeptr y 
= current -> parent;
        
while (y != nullnode  && current == y -> right)
        
{
            current 
= y;
            y 
= y -> parent;
        }

        
return y;
    }

    inline nodeptr succ(
int x)
    
{
        
return succ(find(x));
    }

    
//返回前驱
    inline nodeptr pred(nodeptr current)
    
{
        
if (current == NULL)
            
return NULL;
        
if (current -> left != nullnode)
            
return max(current -> left);
        nodeptr y 
= current -> parent;
        
while (y != nullnode  && current == y -> left)
        
{
            current 
= y;
            y 
= y -> parent;
        }

        
return y;
    }

    inline nodeptr pred(
int x)
    
{
        
return pred(find(x));
    }

    inline nodeptr select(
int i)
    
{
        
return select(root, i);
    }

    
//返回x在树中的位置
    inline int rank(nodeptr x)
    
{
        
int r = x -> left -> size + 1;
        nodeptr y 
= x;
        
while (y != root)
        
{
            
if (y == y -> parent -> right)
                r 
+= y -> parent -> left -> size +1;
            y 
= y -> parent;
        }

        
return r;
    }

}
;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值