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=;}
}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手写版的更多相关文章
- .NET Services Stack笔记之手写版
- 手写Tomcat
学习JavaWeb之后,只知道如何部署项目到Tomcat中,而并不了解其内部如何运行,底层原理为何,因此写下此篇博客初步探究一下.学习之前需要知识铺垫已列出:Tomcat目录结构.HTTP协议.IO. ...
- 用MXnet实战深度学习之一:安装GPU版mxnet并跑一个MNIST手写数字识别
用MXnet实战深度学习之一:安装GPU版mxnet并跑一个MNIST手写数字识别 http://phunter.farbox.com/post/mxnet-tutorial1 用MXnet实战深度学 ...
- 手写一套迷你版HTTP服务器
本文主要介绍如何通过netty来手写一套简单版的HTTP服务器,同时将关于netty的许多细小知识点进行了串联,用于巩固和提升对于netty框架的掌握程度. 服务器运行效果 服务器支持对静态文件css ...
- 手写队列以及stl中队列的使用
一,手写队列. struct queue { ; ,rear=,a[maxn]; void push(int x) { a[++rear]=x; } void pop() { first++; } i ...
- gcd手写代码及STL中的使用方法
一.手写代码 inline int gcd(int x,int y){ if(y==0) return x; else return(gcd(y,x%y)); } 二.STL中的使用方法 注:在STL ...
- MNIST手写数字分类simple版(03-2)
simple版本nn模型 训练手写数字处理 MNIST_data数据 百度网盘链接:https://pan.baidu.com/s/19lhmrts-vz0-w5wv2A97gg 提取码:cgnx ...
- 闭关修炼180天--手写持久层框架(mybatis简易版)
闭关修炼180天--手写持久层框架(mybatis简易版) 抛砖引玉 首先先看一段传统的JDBC编码的代码实现: //传统的JDBC实现 public static void main(String[ ...
- 手写简易版RPC框架基于Socket
什么是RPC框架? RPC就是远程调用过程,实现各个服务间的通信,像调用本地服务一样. RPC有什么优点? - 提高服务的拓展性,解耦.- 开发人员可以针对模块开发,互不影响.- 提升系统的可维护性及 ...
随机推荐
- cocos2dx基础篇(19) 基本动作CCAction
[3.x] (1)去掉"CC" (2)新增了一些动作:(精力有限,新增的动作请自行摸索) > EaseBezierAction > EaseQuadra ...
- Win10.Shift+鼠标右键_CMD(管理员)
1.资料: 1.1.Windows10下设置Shift+右键增加cmd - wyx0712的博客 - CSDN博客.html(https://blog.csdn.net/wyx0712/article ...
- zabbix_server.conf
ListenPort=10051 LogFile=/var/log/zabbix/zabbix_server.log LogFileSize=0 PidFile=/var/run/zabbix/zab ...
- [DataContract]和[DataMember]缺少引用
1.项目->右键->添加引用->找到System.Runtime.Serialization 2.代码中加上 Using System.Runtime.Serialization
- 第六周总结&第四次实验报告
实验四 类的继承 一. 实验目的 (1) 掌握类的继承方法: (2) 变量的继承和覆盖,方法的继承.重载和覆盖实现: 二. 实验内容 三.实验过程 实验代码 package Shiyan4; publ ...
- ubuntu 虚拟机安装
ubuntu16.04.5 LTS 安装 1.下载ubuntu镜像 打开ubuntu官网镜像地址https://launchpad.net/ubuntu/+cdmirrors 在上面中搜索chin ...
- Java数据结构之栈(Stack)
1.栈(Stack)的介绍 栈是一个先入后出(FILO:First In Last Out)的有序列表. 栈(Stack)是限制线性表中元素的插入和删除只能在同一端进行的一种特殊线性表. 允许插入和删 ...
- Spring框架 课程笔记
Spring框架 课程笔记 第1章 Spring概述 1.1 Spring概述 1) Spring是一个开源框架 2) Spring为简化企业级开发而生,使用Spring ...
- ajax异步加载分页评论带点赞功能
<script type="text/javascript" src="__ROOT__/Index/Tpl/Public/js/jquery.js"&g ...
- JProfiler监控
原文: https://blog.csdn.net/jijilan/article/details/83022715