zoukankan      html  css  js  c++  java
  • C++STL手写版

    手写STL,卡常专用。

    node为变量类型,可以自由定义,以下不再赘述。

    1、stack(栈)

      开一个数组,和一个top指针,压栈时++,弹栈时--即可。

    struct stack{
        int tp;node st[N];
        node top(){return st[tp];}
        void push(node x){st[++tp]=x;}
        void pop(){--tp;}
        bool empty(){return !tp;}
        void size(){return tp;}
        void clear(){tp=0;}
    }s;

    2、queue(循环队列)

      用两个指针,记录队头和队尾,达到两端时特判即可。

    struct queue{
        int l,r,cnt;node qu[N];
        node front(){return qu[l];}
        void ne(int &x){++x;if(x==N) x=1;}
        void push(node x){ne(r);qu[r]=x;++cnt;}
        void pop(){ne(l);--cnt;}
        bool empty(){return !cnt;}
        void size(){return cnt;}
        void clear(){r=cnt=0,l=1;}
    }q;

    3、deque(双端队列)

      和队列类似。

    struct deque{
        int l,r,cnt;node qu[N];
        void init(){r=cnt=0,l=1;}
        node front(){return qu[l];}
        node back(){return qu[r];}
        void ne(int &x){++x;if(x==N) x=1;}
        void la(int &x){--x;if(!x) x=N-1;}
        void push_front(node x){la(l);qu[l]=x;++cnt;}
        void push_back(node x){ne(r);qu[r]=x;++cnt;}
        void pop_front(){ne(l);--cnt;}
        void pop_back(){la(r);--cnt;}
        bool empty(){return !cnt;}
        void size(){return cnt;}
        void clear(){r=cnt=0,l=1;}
    }q;

    4、priority_queue(优先队列)

      具有强大的功能,可以删除任意一个元素。

      使用时在node内部重载"<"号,删除元素传该元素的id。

      %%%remarkable的手写堆是假的,通常情况下删除堆中元素时并不知道它在堆中的下标,而是知道id。

      id值可以在node里维护,就对id开一个互逆数组,同时交换即可。

    struct priority_queue{
        int cnt,p[N];node heap[N];
        void up(int x){
            while(x>1&&heap[x>>1]<heap[x]){
                swap(p[heap[x>>1].id],p[heap[x].id]);
                swap(heap[x>>1],heap[x]);
                x>>=1;
            }
        }
        void down(int x){
            int y=x<<1;
            while(y<=cnt){
                if(y<cnt&&heap[y]<heap[y|1]) y|=1;
                if(heap[x]<heap[y]){
                    swap(p[heap[x].id],p[heap[y].id]);
                    swap(heap[x],heap[y]);
                    x=y;y=x<<1;
                }
                else break;
            }
        }
        int size(){return cnt;}
        bool empty(){return !cnt;}
        void push(node x){heap[++cnt]=x;p[x.id]=cnt;up(cnt);}
        node top(){return heap[1];}
        void pop(){
            swap(p[heap[1].id],p[heap[cnt].id]);
            swap(heap[1],heap[cnt]);
            p[heap[cnt].id]=0;cnt--;
            if(cnt) down(1);
        }
        void remove(int x){
            x=p[x];
            swap(p[heap[x].id],p[heap[cnt].id]);
            swap(heap[x],heap[cnt]);
            p[heap[cnt].id]=0;cnt--;
            if(x<=cnt){up(x);down(x);}
        }
        void clear(){cnt=0;}
    }q;

    5、bitset(多位二进制数)

      ct数组需预处理,表示每个数中1的个数。

    struct bitset{
        unsigned long long a[N];
        const unsigned long long m=65535;
        void clear(){memset(a,0,sizeof(a));}
        void set(){for(int i=0;i<N;i++) a[i]=m+(m<<16)+(m<<32)+(m<<48);}
        void reset(){clean();}
        void flip(){for(int i=0;i<N;i++) a[i]^=(m+(m<<16)+(m<<32)+(m<<48));}
        void set(int x,int y){
            if(y==1) a[x/64]|=(unsigned long long)1<<(x&63);
            else if((a[x/64]>>(x&63))&1) a[x/64]^=(unsigned long long)1<<(x&63);
        }    
        void reset(int x){set(x,0);}
        void flip(int x){
            a[x/64]^=(unsigned long long)1<<(x&63);
        }
        friend bitset operator | (const bitset &x,const bitset &y){
            bitset ans;ans.clear();
            for(int i=0;i<N;i++) ans.a[i]=x.a[i]^y.a[i];
            return ans;
        }
        friend bitset operator & (const bitset &x,const bitset &y){
            bitset ans;ans.clear();
            for(int i=0;i<N;i++) ans.a[i]=x.a[i]^y.a[i];
            return ans;
        }
        friend bitset operator ^ (const bitset &x,const bitset &y){
            bitset ans;ans.clear();
            for(int i=0;i<N;i++) ans.a[i]=x.a[i]^y.a[i];
            return ans;
        }
        friend void operator |= (bitset &x,const bitset &y){
            for(int i=0;i<N;i++) x.a[i]|=y.a[i];
            return ;
        }
        friend void operator &= (bitset &x,const bitset &y){
            for(int i=0;i<N;i++) x.a[i]&=y.a[i];
            return ;
        }
        friend void operator ^= (bitset &x,const bitset &y){
            for(int i=0;i<N;i++) x.a[i]^=y.a[i];
            return ;
        }
        int count(){
            int cnt=0;
            for(int i=0;i<N;i++) cnt+=ct[a[i]&m]+ct[(a[i]>>16)&m]+ct[(a[i]>>32)&m]+ct[(a[i]>>48)&m];
            return cnt;
        }
        bool any(){return count();}
        bool none(){return !count();}
    }b;

    6、set/map(红黑树)

      1 #include<iostream>
      2 #include<cstdio>
      3 #define Red true
      4 #define Black false
      5 using namespace std;
      6 const int N=400005;
      7 int n;
      8 struct node{
      9     int key,si,we,co;
     10     node *f,*ch[2];
     11     void fill(int _key,int _co,int _we,node *now){//初始化节点信息
     12         this->key=_key;this->co=_co;
     13         this->si=this->we=_we; 
     14         this->f=this->ch[0]=this->ch[1]=now;
     15     }
     16     void pushup(){//上传更新
     17         this->si=this->ch[0]->si+this->ch[1]->si+this->we;
     18     }
     19     void pushdown(){//也是上传更新
     20         for(node *now=this;now->si;now=now->f) now->si--;
     21     }
     22     int getpos(int x){//判断向左或向右走
     23         return (this->key==x)?-1:(x>this->key);
     24     }
     25 }I;
     26 struct Red_Black_Tree{
     27     int cnt;
     28     node *rt,*nul;//红黑树没有空指针,所有空指针指向nul
     29     node pool[N],*tail,*re[N];//内存池
     30     void init(){//初始化
     31         cnt=0;tail=&pool[cnt];nul=tail++;
     32         nul->fill(0,Black,0,NULL);rt=nul;
     33     }
     34     node *New(int key){//新建节点
     35         node *now=nul;
     36         if(!cnt) now=tail++;
     37         else now=re[--cnt];
     38         now->fill(key,Red,1,nul);//新节点为红色
     39         return now;
     40     }
     41     void rotate(node *now,int pos){//旋转操作
     42         node *c=now->ch[pos^1];
     43         now->ch[pos^1]=c->ch[pos];
     44         if(c->ch[pos]->si) c->ch[pos]->f=now;
     45         c->f=now->f;
     46         if(!now->f->si) rt=c;//旋到根
     47         else now->f->ch[now->f->ch[0]!=now]=c;
     48         c->ch[pos]=now;now->f=c;c->si=now->si;
     49         now->pushup();
     50     }
     51     void insert_transfrom(node *now){//插入调整
     52         for(;now->f->co;){//当父亲为红色,不合法,需要调整
     53             node *fa=now->f,*gr=fa->f;
     54             int pos=fa==gr->ch[0];node *un=gr->ch[pos];
     55             if(un->co){//叔叔是红色,父亲和叔叔同时染成黑色
     56                 fa->co=un->co=Black;
     57                 gr->co=Red;now=gr;
     58             }
     59             else if(now==fa->ch[pos]) rotate(now=fa,pos^1);//父亲不是根
     60             else{
     61                 gr->co=Red;fa->co=Black;rotate(gr,pos);
     62             }
     63         }
     64         rt->co=Black;//根必须是黑色
     65     }
     66     void remove_transfrom(node *now){//删除调节
     67         for(;now!=rt&&!now->co;){
     68             int pos=now==now->f->ch[0];
     69             node *fa=now->f,*br=fa->ch[pos];
     70             if(br->co){//调节颜色一致
     71                 br->co=Black;fa->co=Red;
     72                 rotate(now->f,pos^1);
     73                 br=fa->ch[pos];
     74             }
     75             else if(!br->ch[0]->co&&!br->ch[1]->co){//兄弟的两个儿子都是黑色
     76                 br->co=Red;now=fa;//兄弟染成红色
     77             }
     78             else{
     79                 if(!br->ch[pos]->co){//保持路径上黑色节点数相同
     80                     br->ch[pos^1]->co=Black;br->co=Red;
     81                     rotate(br,pos);br=fa->ch[pos];
     82                 }
     83                 br->co=fa->co;br->ch[pos]->co=fa->co=Black;
     84                 rotate(fa,pos^1);break;
     85             }
     86         }
     87         now->co=Black;
     88     }
     89     void insert(int key){//插入节点
     90         node *now=rt,*fa=nul;int pos;
     91         for(;now->si;now=now->ch[pos]){
     92             now->si++;fa=now;
     93             pos=now->getpos(key);
     94             if(pos==-1){//找到对应值
     95                 now->we++;return;
     96             }
     97         }
     98         now=New(key);//找到位置,插入节点
     99         if(fa->si) fa->ch[key>fa->key]=now;
    100         else rt=now;
    101         now->f=fa;insert_transfrom(now);
    102     }
    103     node *find(node *now,int key){//查找位置
    104         for(;now->si&&now->key!=key;now=now->ch[now->key<key]);
    105         return now;
    106     }
    107     void remove(int key){
    108         node *res=find(rt,key);
    109         if(!res->si) return;//没有找到
    110         if(res->we>1){//有多个,只删除一个
    111             res->we--;res->pushdown();return;
    112         }
    113         node *fa=res,*now=nul;
    114         if(res->ch[0]->si&&res->ch[1]->si){//有两个儿子,找节点替代自己
    115             for(fa=res->ch[1];fa->ch[0]->si;fa=fa->ch[0]);//找后继
    116         }
    117         now=fa->ch[!fa->ch[0]->si];now->f=fa->f;
    118         if(!fa->f->si) rt=now;//当前点是根
    119         else fa->f->ch[fa->f->ch[1]==fa]=now;
    120         if(res!=fa){
    121             res->key=fa->key;res->we=fa->we;
    122         }
    123         fa->f->pushdown();
    124         for(node *st=fa->f;fa->we>1&&st->si&&st!=res;st->si-=fa->we-1,st=st->f);
    125         if(!fa->co) remove_transfrom(now);
    126         re[cnt++]=fa;//回收内存
    127     }
    128     int rnk(int key){//查排名
    129         int res,ans=0;
    130         for(node *now=rt;now->si;){
    131             res=now->ch[0]->si;
    132             if(now->key==key) break;
    133             else if(now->key>key) now=now->ch[0];
    134             else{
    135                 ans+=res+now->we;now=now->ch[1];
    136             }
    137         }
    138         return ans+res+1;
    139     }
    140     int kth(int k){//查数
    141         int res;node *now=rt;
    142         for(;now->si;){
    143             res=now->ch[0]->si;
    144             if(k<=res) now=now->ch[0];
    145             else if(res+1<=k&&k<=res+now->we) break;
    146             else{
    147                 k-=res+now->we;now=now->ch[1];
    148             }
    149         }
    150         return now->key;
    151     }
    152     int pre(int key){//前驱
    153         int res=0;
    154         for(node *now=rt;now->si;){
    155             if(now->key<key){
    156                 res=now->key;now=now->ch[1];
    157             }
    158             else now=now->ch[0];
    159         }
    160         return res;
    161     }
    162     int nxt(int key){//后继
    163         int res=0;
    164         for(node *now=rt;now->si;){
    165             if(now->key>key){
    166                 res=now->key;now=now->ch[0];
    167             }
    168             else now=now->ch[1];
    169         }
    170         return res;
    171     }
    172 }rbt;
    173 int main()
    174 {
    175     scanf("%d",&n);rbt.init();//初始化
    176     for(int i=1;i<=n;i++){
    177         int op,x;scanf("%d%d",&op,&x);
    178         if(op==1) rbt.insert(x);
    179         else if(op==2) rbt.remove(x);
    180         else if(op==3) printf("%d
    ",rbt.rnk(x));
    181         else if(op==4) printf("%d
    ",rbt.kth(x));
    182         else if(op==5) printf("%d
    ",rbt.pre(x));
    183         else printf("%d
    ",rbt.nxt(x));
    184     }
    185     return 0;
    186 }
    注释版红黑树
  • 相关阅读:
    一、逻辑架构与存储引擎
    三、动态SQL
    九、装饰者模式
    二、Mapper映射文件
    八、适配器模式
    测试开发系列之Python开发mock接口(二)
    测试开发系列之Python开发mock接口(三)
    html基础
    seleniumWebdriver浏览器驱动信息汇总
    用30行代码开发一个上传、下载文件的接口
  • 原文地址:https://www.cnblogs.com/hz-Rockstar/p/11643946.html
Copyright © 2011-2022 走看看