zoukankan      html  css  js  c++  java
  • 平衡树Treap

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    const int INF=0x3fffffff;
    int node_cnt;																//结点计数器 
    struct 	Node;
    typedef Node * pNode; 														//结点指针 
    struct Node																	//结点定义 
    {
    	int	  key, val, size, same;
    	pNode ls, rs;
    	Node(int val):val(val), size(1), same(1){ ls=rs=NULL; key=rand(); }
    	int  lsize(){ return ls?ls->size:0; }									//避免空指针查询 
    	int  rsize(){ return rs?rs->size:0; }									//避免空指针查询 
    	void update(){ size=lsize()+rsize()+same; }
    };
    void zig(pNode &p)															//左旋 
    {
    	pNode tmp=p->rs; p->rs=tmp->ls; tmp->ls=p; tmp->size=p->size; p->update(); p=tmp;
    }
    void zag(pNode &p)															//右旋 
    {
    	pNode tmp=p->ls; p->ls=tmp->rs; tmp->rs=p; tmp->size=p->size; p->update(); p=tmp;
    }
    void treap_insert(int x, pNode &p)											//插入结点 
    {
    	if(!p){ p=new Node(x); node_cnt++; return; };
    	if(p->val==x)	{ p->same++; p->update(); node_cnt++; return; }
    	if(x< p->val)	{ treap_insert(x, p->ls); if(p->key>p->ls->key) zag(p); }
    	if(x> p->val)	{ treap_insert(x, p->rs); if(p->key>p->rs->key) zig(p); }
    	p->update();
    }
    void treap_delete(int x, pNode &p)											//删除结点 
    {
    	if(!p)	return;														 			//没找到 
    	if(x<p->val)	treap_delete(x, p->ls);
    	if(x>p->val)	treap_delete(x, p->rs);
    	if(x==p->val)
    	{
    		if(p->same>1)	{ p->same--;  p->update(); node_cnt--;	return; }			//多个相同的,删除一个 
    		if(!(p->ls) && !(p->rs)){ delete p; p=NULL; node_cnt--;	return; }			//没有子树,直接删除 
    		else if(!p->ls && p->rs){ delete p; p=p->rs; node_cnt--; 		}			//只有右子树 
    		else if(p->ls && !p->rs){ delete p; p=p->ls; node_cnt--;		}			//只有左子树
    		else															 			//有左、右子树
    		{
    			if(p->ls->key<p->rs->key)	zag(p), treap_delete(x, p->rs);
    			else						zig(p), treap_delete(x, p->ls);
    		}
    	}
    	p->update(); 
    }
    int  treap_rank(int x, const pNode &p)										//查询元素排名 
    {
    	if(!p)	return 0;																//没找到 
    	if(p->val==x)		return p->lsize()+1;
    	else if(p->val <x)	return p->lsize()+p->same+treap_rank(x, p->rs);
    	else				return treap_rank(x, p->ls); 								//这个函数是存在问题的,如果要查找的数字不存在,排名就是N或0,该如何解决?
    }																					
    int  treap_find(int k, const pNode &p)										//查询排名为k的元素 
    {
    	if(k>node_cnt)	return INF;														//如果k大于实际节点数,返回无穷大 
    	int tmp=p->lsize()+p->same;
    	if(p->lsize()<k && k<=tmp)	return p->val;
    	else if(k>tmp)				return treap_find(k-tmp, p->rs);
    	else						return treap_find(k, p->ls);
    }
    int  treap_pre(int x, const pNode &p)										//查找x的前驱 
    {
    	if(!p)	return -INF;															//找不到返回无穷小 
    	if(x<=p->val)	return treap_pre(x, p->ls);
    	else			return max(p->val, treap_pre(x, p->rs));
    }
    int  treap_next(int x, const pNode &p)										//查找x的后继 
    {
    	if(!p)	return INF;																//找不到返回无穷大 
    	if(x>=p->val)	return treap_next(x, p->rs);
    	else			return min(p->val, treap_next(x, p->ls));	
    }
    int main()
    {
    	int   n;
    	pNode root=NULL;
    	scanf("%d", &n);
    	for(int i=1, opt, x; i<=n; i++)
    	{
    		scanf("%d%d", &opt, &x);
    		if(opt==1)	treap_insert(x, root);
    		if(opt==2)	treap_delete(x, root);
    		if(opt==3)	printf("%d
    ", treap_rank(x, root));
    		if(opt==4)	printf("%d
    ", treap_find(x, root));
    		if(opt==5)	printf("%d
    ", treap_pre(x, root) );
    		if(opt==6)	printf("%d
    ", treap_next(x, root));
    	}
    	return 0;
    }
    
  • 相关阅读:
    第26月第26天 Domain=AVFoundationErrorDomain Code=-11850
    第26月第25天 ubuntu openjdk-8-jdk jretty
    第26月第23天 nsobject 单例 CFAbsoluteTimeGetCurrent
    第26月第22天 iOS瘦身之armv7 armv7s arm64选用 iOS crash
    第26月第20天 springboot
    第26月第18天 mybatis_spring_mvc pom
    python中的字符数字之间的转换函数
    python if else elif statement
    python 赋值魔法
    python print import使用
  • 原文地址:https://www.cnblogs.com/lfyzoi/p/10773109.html
Copyright © 2011-2022 走看看