zoukankan      html  css  js  c++  java
  • Splay基本操作

    Instructions

    Splay基本操作

    using namespace std;
    struct Splay{
    	int data;
    	int ch[2];
    	int num;
    	int FA;
    	int size;
    }t[maxn];
    int newp;
    void Rotate(int x){
    	int y=t[x].FA,z=t[y].FA,k=(t[y].ch[1]==x);//y是x的父亲,z是y的父亲(x的祖父),k是x是y的哪个儿子 
    	t[z].ch[y==t[z].ch[1]]=x;//把x变到y原来的位置 
    	t[x].FA=z;//把x的父亲变成z 
    	t[y].ch[k]=t[x].ch[k^1];//把y原来是x的位置的变成x相对于y的位置
    	t[y].size=t[t[y].ch[k]].size+t[t[y].ch[k^1]].size;//把y的size更新 
    	t[t[x].ch[k^1]].FA=y;//修改那个的父亲
    	t[x].ch[k^1]=y;//把x的相应儿子改成y
    	t[x].size==t[y].size+t[t[x].ch[k]].size;//更新x的size 
    	t[y].FA=x;//把y的父亲改成x 
    }
    void splay_S(int x,int destnation){
    	while(t[x].FA!=destnation){//如果没有把x旋成destnation的儿子 
    		int y=t[x].FA,z=t[y].FA;//y父亲,z祖父 
    		if(z!=destnation){//如果祖父还不是destnation 
    			(t[z].ch[0]==y)^(t[y].ch[0]==x)?Rotate(x):Rotate(y);//如果共线旋y不共线旋x 
    		}
    		Rotate(x);//无论共不共线都要旋x 
    	}
    	if(destnation==0)root=x;//如果根节点是0那更新根节点 
    }
    void find(x){//找到x的位置并且把x旋上去 
    	int u=root;
    	if(!u)return;//如果是空树直接return 
    	while(t[u].ch[x>t[u].data]&&x!=t[u].data){//如果还没有找到x的位置 
    		u=t[u].ch[x>t[u].data];//如果x大于data就进右儿子否则进左儿子 
    	}
    	splay_S(x,0);//把x旋上去 
    }
    int Next_n(int x,bool flag){//寻找前驱||后继(flag==0是前驱,flag==1是后继) 
    	find(x);//找到x的位置 
    	int u=root;
    	if(t[u].data<x&&!flag)return u;//如果根节点比x小且是找前驱直接return u 
    	if(t[u].data>x&&flag)return u;//如果根节点比x大且是找后继直接return u
    	u=t[u].ch[flag];//找前驱就找左儿子,后继就右儿子 
    	while(t[u].ch[flag^1]){//当还没有遇到叶子结点的时候 
    		u=t[u].ch[flag^1];//找前驱进入左儿子之后就找最右边的,找后继就进入右儿子之后找最左边的 
    	}
    	return u;//返回前驱或者后继的位置 
    }
    void insert(int x){
    	int u=root,fa=0;
    	while(u&&t[u].data!=x){//当还没有找到x或者还没有找到叶子结点的时候 
    		fa=u;
    		u=t[u].ch[x>t[u].data];
    	}
    	if(u){//如果x已经存在 
    		t[u].num++;//更新该结点的num 
    	}
    	else{//否则 
    		u=++newp;//重新建立一个结点 
    		if(fa){//如果已经有父亲 
    			t[fa].ch[x>t[fa].data]=u;//存成儿子 
    		}
    		t[u].ch[0]=t[u].ch[1]=0;//新加的点是叶子结点没有儿子 
    		t[u].FA=fa;//把父亲更新 
    		t[u].data=x;//更新data 
    		t[u].num=1;//更新num 
    		t[u].size=1;//更新size 
    	}
    	splay_S(u,0);//把该结点旋上去 
    }
    void Delete_d(int x){//删除一个点 
    	int Pre_x=Next_n(x,0);//找前驱 
    	int Suc_x=Next_n(x,1);//找后继 
    	splay_S(Pre_x,0);//把前驱旋到根节点 
    	splay_S(Suc_x,Pre_x);//把后继旋到前驱 
    	int del=t[Suc_x].ch[0];
    	if(t[del].cnt>1){//如果有多个该结点 
    		t[del].cnt--;//删去一个 
    		splay_S(del,0);//旋上去 
    	}
    	else t[Suc_x].ch[0]=0;//否则直接删去这个点 
    }
    
  • 相关阅读:
    【语言处理与Python】6.3评估
    win10同时安装 office2016和visio2016
    如何学好C语言(转)
    数据库索引
    Redis系列(二)如何接受客户端请求并调用处理函数
    Redis系列(三)事件处理细节分析及epoll介绍
    linux下查看某一个程序所使用的内存方法总结
    c++ 二级指针详解&&hiredis api
    C风格字符串
    twemproxy简介
  • 原文地址:https://www.cnblogs.com/virtual-north-Illya/p/10045273.html
Copyright © 2011-2022 走看看