手拆STL

vector

v e c t o r vector vector,动态数组。

先来看一下它的一些基本操作及其拆后残渣。

1.a.push_back(x),将 x x x加入动态数组 a a a的末尾。

实现:a[++cnt]=x

2.a.size(),查询动态数组 a a a中元素的数量。

实现:cnt

3.a.pop_back(),将动态数组 a a a末尾的元素删除。

实现:cnt--

4.a.erase(a.begin()+x),删除动态数组 a a a中第 x + 1 x+1 x+1个元素。

实现:for(int i=x+1;i<=--cnt;i++)a[i]=a[i+1];

5.a.clear(),清空动态数组 a a a。

实现:cnt=0

总体实现:

cpp 复制代码
int a[N];
int cnt;
void Push_back(int x){
	a[++cnt]=x;
}
int Size(){
	return cnt;
}
void Pop_back(){
	cnt--;
}
void Erase(int x){
	for(int i=x+1;i<=--cnt;i++)a[i]=a[i+1];
}
void Clear(){
	cnt=0;
}

queue

q u e u e queue queue,队列。

队列常用的操作:

1.q.push(x),向队列 q q q中加入一个元素 x x x。

实现:q[++tail]=x

2.q.pop(),弹出队列 q q q的队首。

实现: head++

3.q.front(),查询队列 q q q的队首。

实现:q[head+1]

4.q.back(),查询队列 q q q的队尾。

实现:q[tail]

5.q.empty(),判断队列 q q q是否为空。

实现:(head==tail)

6.q.size(),查询队列 q q q的元素个数

实现:tail-head

手写的思想:两个变量 h e a d head head和 t a i l tail tail, h e a d head head存队头前一个元素的下标, t a i l tail tail存队尾的下标。

总体实现:

cpp 复制代码
int q[N];
int head,tail;
void Push(int x){
	q[++tail]=x;
}
void Pop(){
	head++;
}
int Front(){
	return q[head+1];
}
int Back(){
	return q[tail];
}
bool Empty(){
	return head==tail;
}
int Size(){
	return tail-head;
}

deque

d e q u e deque deque,双端队列。

一些基本操作:

1.q.push_back(x),在双端队列 q q q的队尾加入一个元素 x x x。

实现:q[++tail]=x

2.q.push_front(x),在双端队列 q q q的队头加入一个元素 x x x。

实现:q[head--]=x

3.q.front(),查询双端队列 q q q的队头。

实现:q[head+1]

4.q.back(),查询双端队列 q q q的队尾。

实现:q[tail]

5.q.pop_back(),弹出双端队列 q q q的队尾。

实现:tail--

6.q.pop_front(),弹出双端队列 q q q的队头。

实现:head++

手写的思想:两个变量 h e a d head head和 t a i l tail tail,开双倍的数组空间 N N N,将 h e a d head head和 t a i l tail tail都初始化为 N 2 \frac{N}{2} 2N, h e a d head head存队头前一个元素的下标, t a i l tail tail存队尾的下标。

总体实现:

cpp 复制代码
int q[N];
int head=N/2,tail=N/2;
void Push_back(int x){
	q[++tail]=x;
}
void Push_front(int x){
	q[head--]=x;
}
int Front(){
	return q[head+1];
}
int Back(){
	return q[tail];
}
void Pop_back(){
	tail--;
}
void Pop_front(){
	head++;
}

priority_queue

p r i o r i t y q u e u e priority_queue priorityqueue,优先队列。

要拆优先队列,首先得明白优先队列的运行规则。

优先队列实际上是在维护一个二叉堆

二叉堆就是一颗完全二叉树,那么要维护这个二叉堆的什么状态呢?

答案是维护二叉堆的每一个非叶子节点的值都大于等于(或者小于等于)它的两个儿子的值。
那么......开拆。(大根堆)

优先队列的常用操作:

1.q.push(x),将元素 x x x加入优先队列 q q q。

对于一个元素,从左至右依次加入二叉堆,如果父亲节点有了这个儿子之后就违法了,那么它就当父亲了,父亲自然成了儿子。

例如向下面这个二叉堆加入一个元素 7 7 7。

实现:

cpp 复制代码
void Push(int x){
	q[++cnt]=x;
	int p=cnt;
	while(p>1&&q[p/2]<q[p])swap(q[p/2],q[p]),p/=2;//维护单调性
}

2.q.top(),返回优先队列 q q q中的最值

实现:由于时刻都在维护二叉堆的单调性,所以最值就是q[1]

3.q.pop(),弹出优先队列 q q q的队头(最值)。

实现:

cpp 复制代码
void Pop(){
	q[1]=q[cnt--];
	q[cnt+1]=0;
	int p=1;
	while(p<=cnt&&q[p]<max(q[p*2],q[p*2+1])){//维护
		//判断左儿子和右儿子哪一个更大
		if(q[p*2]>q[p*2+1])swap(q[p],q[p*2]),p*=2;
		else swap(q[p],q[p*2+1]),p=p*2+1;
	}
}

思想:维护一个二叉堆。

总体实现:

cpp 复制代码
int q[N];
int cnt;
void Push(int x){
	q[++cnt]=x;
	int p=cnt;
	while(p>1&&q[p/2]<q[p])swap(q[p/2],q[p]),p/=2;
}
int Top(){
	return q[1];
}
void Pop(){
	q[1]=q[cnt--];
	q[cnt+1]=0;
	int p=1;
	while(p<=cnt&&q[p]<max(q[p*2],q[p*2+1])){
		if(q[p*2]>q[p*2+1])swap(q[p],q[p*2]),p*=2;
		else swap(q[p],q[p*2+1]),p=p*2+1;
	}
}

stack

s t a c k stack stack,栈。

栈的基本操作:

1.t.push(x),将元素 x x x加入栈 t t t中。

实现:t[++cnt]=x

2.t.pop(),弹出栈 t t t的栈顶。

实现:cnt--

3.t.top(),查询栈 t t t的栈顶元素。

实现:t[cnt]

4.t.empty,判断栈 t t t是否为空。

实现:(!cnt)

5.t.size(),查询栈 t t t的元素个数。

实现:cnt

总体实现:

cpp 复制代码
int t[N];
int cnt;
void Push(int x){
	t[++cnt]=x;
}
void Pop(){
	cnt--;
}
int Top(){
	return t[cnt];
}
bool Empty(){
	return !cnt;
}
int Size(){
	return cnt;
}
相关推荐
PD我是你的真爱粉18 小时前
Redis 持久化、过期删除、淘汰策略与内存碎片全解析
java·redis·bootstrap
Percep_gan18 小时前
在芋道自定义数据权限
java·数据库
哆啦阿梦18 小时前
Java AI 应用工程师 - 完整技能清单
java·开发语言·人工智能
磊 子18 小时前
八大排序之插入排序+希尔排序
数据结构·算法·排序算法
VT LI18 小时前
Lua 源码执行流程全解析:词法分析、语法分析、字节码生成、虚拟机执行与垃圾回收
java·开发语言·lua
kishu_iOS&AI18 小时前
机器学习 —— 逻辑回归(混淆矩阵)
人工智能·算法·机器学习·逻辑回归
W230357657318 小时前
经典算法:打家劫舍(动态规划 + 回溯求最优解)C++ 超详细解析
c++·算法·动态规划
Dev7z18 小时前
基于改进小波阈值的sEMG信号降噪与手势识别系统设计与实现
算法·手势识别·改进小波阈值·semg·信号降噪
凤山老林20 小时前
04-Java JDK, JRE和JVM
java·开发语言·jvm
灵感__idea1 天前
Hello 算法:贪心的世界
前端·javascript·算法