手写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=;}
}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=;}
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=,l=;}
}q;

3、deque(双端队列)

  和队列类似。

struct deque{
int l,r,cnt;node qu[N];
void init(){r=cnt=,l=;}
node front(){return qu[l];}
node back(){return qu[r];}
void ne(int &x){++x;if(x==N) x=;}
void la(int &x){--x;if(!x) x=N-;}
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=,l=;}
}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>&&heap[x>>]<heap[x]){
swap(p[heap[x>>].id],p[heap[x].id]);
swap(heap[x>>],heap[x]);
x>>=;
}
}
void down(int x){
int y=x<<;
while(y<=cnt){
if(y<cnt&&heap[y]<heap[y|]) y|=;
if(heap[x]<heap[y]){
swap(p[heap[x].id],p[heap[y].id]);
swap(heap[x],heap[y]);
x=y;y=x<<;
}
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[];}
void pop(){
swap(p[heap[].id],p[heap[cnt].id]);
swap(heap[],heap[cnt]);
p[heap[cnt].id]=;cnt--;
if(cnt) down();
}
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]=;cnt--;
if(x<=cnt){up(x);down(x);}
}
void clear(){cnt=;}
}q;

5、bitset(多位二进制数)

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

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

6、set/map(红黑树)

 #include<iostream>
#include<cstdio>
#define Red true
#define Black false
using namespace std;
const int N=;
int n;
struct node{
int key,si,we,co;
node *f,*ch[];
void fill(int _key,int _co,int _we,node *now){//初始化节点信息
this->key=_key;this->co=_co;
this->si=this->we=_we;
this->f=this->ch[]=this->ch[]=now;
}
void pushup(){//上传更新
this->si=this->ch[]->si+this->ch[]->si+this->we;
}
void pushdown(){//也是上传更新
for(node *now=this;now->si;now=now->f) now->si--;
}
int getpos(int x){//判断向左或向右走
return (this->key==x)?-:(x>this->key);
}
}I;
struct Red_Black_Tree{
int cnt;
node *rt,*nul;//红黑树没有空指针,所有空指针指向nul
node pool[N],*tail,*re[N];//内存池
void init(){//初始化
cnt=;tail=&pool[cnt];nul=tail++;
nul->fill(,Black,,NULL);rt=nul;
}
node *New(int key){//新建节点
node *now=nul;
if(!cnt) now=tail++;
else now=re[--cnt];
now->fill(key,Red,,nul);//新节点为红色
return now;
}
void rotate(node *now,int pos){//旋转操作
node *c=now->ch[pos^];
now->ch[pos^]=c->ch[pos];
if(c->ch[pos]->si) c->ch[pos]->f=now;
c->f=now->f;
if(!now->f->si) rt=c;//旋到根
else now->f->ch[now->f->ch[]!=now]=c;
c->ch[pos]=now;now->f=c;c->si=now->si;
now->pushup();
}
void insert_transfrom(node *now){//插入调整
for(;now->f->co;){//当父亲为红色,不合法,需要调整
node *fa=now->f,*gr=fa->f;
int pos=fa==gr->ch[];node *un=gr->ch[pos];
if(un->co){//叔叔是红色,父亲和叔叔同时染成黑色
fa->co=un->co=Black;
gr->co=Red;now=gr;
}
else if(now==fa->ch[pos]) rotate(now=fa,pos^);//父亲不是根
else{
gr->co=Red;fa->co=Black;rotate(gr,pos);
}
}
rt->co=Black;//根必须是黑色
}
void remove_transfrom(node *now){//删除调节
for(;now!=rt&&!now->co;){
int pos=now==now->f->ch[];
node *fa=now->f,*br=fa->ch[pos];
if(br->co){//调节颜色一致
br->co=Black;fa->co=Red;
rotate(now->f,pos^);
br=fa->ch[pos];
}
else if(!br->ch[]->co&&!br->ch[]->co){//兄弟的两个儿子都是黑色
br->co=Red;now=fa;//兄弟染成红色
}
else{
if(!br->ch[pos]->co){//保持路径上黑色节点数相同
br->ch[pos^]->co=Black;br->co=Red;
rotate(br,pos);br=fa->ch[pos];
}
br->co=fa->co;br->ch[pos]->co=fa->co=Black;
rotate(fa,pos^);break;
}
}
now->co=Black;
}
void insert(int key){//插入节点
node *now=rt,*fa=nul;int pos;
for(;now->si;now=now->ch[pos]){
now->si++;fa=now;
pos=now->getpos(key);
if(pos==-){//找到对应值
now->we++;return;
}
}
now=New(key);//找到位置,插入节点
if(fa->si) fa->ch[key>fa->key]=now;
else rt=now;
now->f=fa;insert_transfrom(now);
}
node *find(node *now,int key){//查找位置
for(;now->si&&now->key!=key;now=now->ch[now->key<key]);
return now;
}
void remove(int key){
node *res=find(rt,key);
if(!res->si) return;//没有找到
if(res->we>){//有多个,只删除一个
res->we--;res->pushdown();return;
}
node *fa=res,*now=nul;
if(res->ch[]->si&&res->ch[]->si){//有两个儿子,找节点替代自己
for(fa=res->ch[];fa->ch[]->si;fa=fa->ch[]);//找后继
}
now=fa->ch[!fa->ch[]->si];now->f=fa->f;
if(!fa->f->si) rt=now;//当前点是根
else fa->f->ch[fa->f->ch[]==fa]=now;
if(res!=fa){
res->key=fa->key;res->we=fa->we;
}
fa->f->pushdown();
for(node *st=fa->f;fa->we>&&st->si&&st!=res;st->si-=fa->we-,st=st->f);
if(!fa->co) remove_transfrom(now);
re[cnt++]=fa;//回收内存
}
int rnk(int key){//查排名
int res,ans=;
for(node *now=rt;now->si;){
res=now->ch[]->si;
if(now->key==key) break;
else if(now->key>key) now=now->ch[];
else{
ans+=res+now->we;now=now->ch[];
}
}
return ans+res+;
}
int kth(int k){//查数
int res;node *now=rt;
for(;now->si;){
res=now->ch[]->si;
if(k<=res) now=now->ch[];
else if(res+<=k&&k<=res+now->we) break;
else{
k-=res+now->we;now=now->ch[];
}
}
return now->key;
}
int pre(int key){//前驱
int res=;
for(node *now=rt;now->si;){
if(now->key<key){
res=now->key;now=now->ch[];
}
else now=now->ch[];
}
return res;
}
int nxt(int key){//后继
int res=;
for(node *now=rt;now->si;){
if(now->key>key){
res=now->key;now=now->ch[];
}
else now=now->ch[];
}
return res;
}
}rbt;
int main()
{
scanf("%d",&n);rbt.init();//初始化
for(int i=;i<=n;i++){
int op,x;scanf("%d%d",&op,&x);
if(op==) rbt.insert(x);
else if(op==) rbt.remove(x);
else if(op==) printf("%d\n",rbt.rnk(x));
else if(op==) printf("%d\n",rbt.kth(x));
else if(op==) printf("%d\n",rbt.pre(x));
else printf("%d\n",rbt.nxt(x));
}
return ;
}

注释版红黑树

C++STL手写版的更多相关文章

  1. .NET Services Stack笔记之手写版

  2. 手写Tomcat

    学习JavaWeb之后,只知道如何部署项目到Tomcat中,而并不了解其内部如何运行,底层原理为何,因此写下此篇博客初步探究一下.学习之前需要知识铺垫已列出:Tomcat目录结构.HTTP协议.IO. ...

  3. 用MXnet实战深度学习之一:安装GPU版mxnet并跑一个MNIST手写数字识别

    用MXnet实战深度学习之一:安装GPU版mxnet并跑一个MNIST手写数字识别 http://phunter.farbox.com/post/mxnet-tutorial1 用MXnet实战深度学 ...

  4. 手写一套迷你版HTTP服务器

    本文主要介绍如何通过netty来手写一套简单版的HTTP服务器,同时将关于netty的许多细小知识点进行了串联,用于巩固和提升对于netty框架的掌握程度. 服务器运行效果 服务器支持对静态文件css ...

  5. 手写队列以及stl中队列的使用

    一,手写队列. struct queue { ; ,rear=,a[maxn]; void push(int x) { a[++rear]=x; } void pop() { first++; } i ...

  6. gcd手写代码及STL中的使用方法

    一.手写代码 inline int gcd(int x,int y){ if(y==0) return x; else return(gcd(y,x%y)); } 二.STL中的使用方法 注:在STL ...

  7. MNIST手写数字分类simple版(03-2)

    simple版本nn模型 训练手写数字处理 MNIST_data数据   百度网盘链接:https://pan.baidu.com/s/19lhmrts-vz0-w5wv2A97gg 提取码:cgnx ...

  8. 闭关修炼180天--手写持久层框架(mybatis简易版)

    闭关修炼180天--手写持久层框架(mybatis简易版) 抛砖引玉 首先先看一段传统的JDBC编码的代码实现: //传统的JDBC实现 public static void main(String[ ...

  9. 手写简易版RPC框架基于Socket

    什么是RPC框架? RPC就是远程调用过程,实现各个服务间的通信,像调用本地服务一样. RPC有什么优点? - 提高服务的拓展性,解耦.- 开发人员可以针对模块开发,互不影响.- 提升系统的可维护性及 ...

随机推荐

  1. VMware克隆虚拟机后mac地址重新设置

    ifconfig eth1   确定新网卡的MAC地址. nmcli con 确定新网卡的UUID vim /etc/udev/rules.d/70-persistent-net.rules 把原et ...

  2. word2vec (CBOW、分层softmax、负采样)

    本文介绍 wordvec的概念 语言模型训练的两种模型CBOW+skip gram word2vec 优化的两种方法:层次softmax+负采样 gensim word2vec默认用的模型和方法 未经 ...

  3. HTML5实现绘制几何图形

    HTML5新增了一个<canvas.../>属性.该元素自身并不绘制图形,只是相当于一张空画布.如果开发者需要向<canvas.../>上绘制图形则必须使用JavaScript ...

  4. 【Qt开发】Qt中图像的显示与基本操作

    Qt可显示基本的图像类型,利用QImage.QPxmap类可以实现图像的显示,并且利用类中的方法可以实现图像的基本操作(缩放.旋转). 1. Qt可显示的图像类型 参考Qt的帮助文档,可支持的类型,即 ...

  5. 20191128 Spring Boot官方文档学习(9.9)

    9.9.数据存取 Spring Boot包含许多用于处理数据源的启动器. 9.9.1.配置自定义数据源 要配置自己的DataSource,请在配置中定义该类型的@Bean.Spring Boot可以在 ...

  6. jenkins初级使用篇

    1.jenkins的初级使用 1.1 介绍 创建一个项目 可以看到当前登陆用户及用户权限 可以查看到所有构建过的项目的历史 系统管理 My Views:视图功能,我们可以自己创建一个自己的视图 系统管 ...

  7. python 并发编程 多进程 队列目录

    python 并发编程 多进程 队列 python 并发编程 多进程 生产者消费者模型介绍 python 并发编程 多进程 生产者消费者模型总结 python 并发编程 多进程 JoinableQue ...

  8. python 并发编程 多进程 Process对象的其他属性方法 terminate与is_alive name pid 函数

    进程对象的其他方法一: terminate与is_alive is_alive()  立刻查看的子进程结果 是否存活 from multiprocessing import Process impor ...

  9. 第十七周周总结 Swing

    考试系统 1.登录功能 用户和密码存在在哪里? 文件 2.考试功能 考试题目和答案存在哪? 文件 3.展示功能 GUI Graphical User Interface图形用户接口 #GUI Java ...

  10. linux安装五笔拼音混输 的五笔输入法

    打开终端先卸载系统的iBus sudo apt-get remove ibus 添加源sudo add-apt-repository ppa:fcitx-team/nightlysudo apt-ge ...