目录
单调队列:
单链表
问题:用vector模拟单链表,实现三种操作
(1)向链表头插入一个数; H
(2)删除第 k 个插入的数后面的数; D K X
(3)在第 k 个插入的数后插入一个数 I K X
n表示共有n次操作,以上是命令,执行结束后,打印链表
本质:idx是核心,idx:链表尾节点的索引
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 10010;
int e[N], ne[N];
int idx, head;
void init()
{
head = -1;//头节点初始化尾-1
idx = 0;//当前位置索引初始化为0
}
void add_to_head(int x)//头插
{
e[idx] = x;//存储值
ne[idx] = head;//将idx的下一个位置连接为head
head = idx;//此时换头
idx++;//当前操作索引++
}
void del(int k)
{
ne[k] = ne[ne[k]];//即将这个点的存的下一个位置的地址改为后两个的地址
//next=next->next;
}
void add(int k, int x)
{
e[idx] = x;
ne[idx] = ne[k];//将k位置的下一个地址存储入新节点,
//相当于新节点此时指向原来k节点指向的下一个位置
ne[k] = idx;//将k的下一个位置指向新开的节点
idx++;//当前操作位置索引++
}
int main()
{
init();
int n;
cin >> n;
while (n--)
{
char op;
int x;
cin >> op;
if (op == 'H')
{
cin >> x;
add_to_head(x);
}
else if (op == 'D')
{
cin >> x;
if (!x) head = ne[head];
else del(x - 1);
}
else if (op == 'I')
{
int k;
cin >> k >> x;
add(k - 1, x);
}
}
for (int i = head; i != -1; i = ne[i])
{
cout << e[i] << " ";
}
return 0;
}
双链表
问题:
实现一个双链表,双链表初始为空,支持 5种操作:
在最左侧插入一个数;
在最右侧插入一个数;
将第 k个插入的数删除;
在第 k 个插入的数左侧插入一个数;
在第 k个插入的数右侧插入一个数
#include<iostream>
#include<vector>
using namespace std;
const int N = 10010;
int m;
int e[N], l[N], r[N];
int idx;
void init()
{
l[1] = 0;
r[0] = 1;
idx = 2;
}
void add(int k, int x)
{
e[idx] = x;
l[idx] = k;
r[idx] = r[k];
l[r[k]] == idx;
r[k] = idx;
idx++;
}
void remove(int k)
{
r[l[k]] = r[k];
l[r[k]] = l[k];
}
int main(void)
{
ios::sync_with_stdio(false);
cin >> m;
init();
while (m--)
{
string op;
cin >> op;
int k, x;
if (op == "R")
{
cin >> x;
add(l[1], x); //! 0和 1 只是代表 头和尾 所以 最右边插入 只要在 指向 1的 那个点的右边插入就可以了
}
else if (op == "L")//! 同理 最左边插入就是 在指向 0的数的左边插入就可以了 也就是可以直接在 0的 有右边插入
{
cin >> x;
add(0, x);
}
else if (op == "D")
{
cin >> k;
remove(k + 1);
}
else if (op == "IL")
{
cin >> k >> x;
add(l[k + 1], x);
}
else
{
cin >> k >> x;
add(k + 1, x);
}
}
for (int i = r[0]; i != 1; i = r[i]) cout << e[i] << ' ';
return 0;
}
栈
题目:实现一个栈,栈初始为空,支持四种操作
push x– 向栈顶插入一个数 xx;pop– 从栈顶弹出一个数;empty– 判断栈是否为空;query– 查询栈顶元素
有n个操作,其中操作4返回栈顶元素,操作3表示yes or no
#include<iostream>
#include<vector>
using namespace std;
const int N = 10010;
int stk[N];
int hh = -1;
int main()
{
int n;
cin >> n;
while (n--)
{
string op;
int x;
cin >> op;
if (op == "push")
{
cin >> x;
stk[++hh] = x;
}
else if (op == "pop")
{
hh--;
}
else if(op == "empty")
{
if (hh == -1) cout << "YES" << endl;
else cout << "NO" << endl;
}
else if (op == "query")
{
cout << stk[hh] << endl;
}
}
return 0;
}
例题:
#include <iostream>
#include <stack>
#include <string>
#include <unordered_map>
using namespace std;
stack<int> num;
stack<char> op;
//优先级表
unordered_map<char, int> h{ {'+', 1}, {'-', 1}, {'*',2}, {'/', 2} };
void eval()//求值
{
int a = num.top();//第二个操作数
num.pop();
int b = num.top();//第一个操作数
num.pop();
char p = op.top();//运算符
op.pop();
int r = 0;//结果
//计算结果
if (p == '+') r = b + a;
if (p == '-') r = b - a;
if (p == '*') r = b * a;
if (p == '/') r = b / a;
num.push(r);//结果入栈
}
int main()
{
string s;//读入表达式
cin >> s;
for (int i = 0; i < s.size(); i++)
{
if (isdigit(s[i]))//数字入栈
{
int x = 0, j = i;//计算数字
while (j < s.size() && isdigit(s[j]))
{
x = x * 10 + s[j] - '0';
j++;
}
num.push(x);//数字入栈
i = j - 1;
}
//左括号无优先级,直接入栈
else if (s[i] == '(')//左括号入栈
{
op.push(s[i]);
}
//括号特殊,遇到左括号直接入栈,遇到右括号计算括号里面的
else if (s[i] == ')')//右括号
{
while(op.top() != '(')//一直计算到左括号
eval();
op.pop();//左括号出栈
}
else
{
while (op.size() && h[op.top()] >= h[s[i]])//待入栈运算符优先级低,则先计算
eval();
op.push(s[i]);//操作符入栈
}
}
while (op.size()) eval();//剩余的进行计算
cout << num.top() << endl;//输出结果
return 0;
}
队列:
#include<iostream>
#include<vector>
using namespace std;
const int N = 10010;
int hh = -1, tt = -1;
int qu[N];
int main()
{
int n;
cin >> n;
while (n--)
{
string op;
int x;
cin >> op;
if (op == "push")
{
cin >> x;
qu[++tt] = x;
}
else if (op == "pop")
{
hh++;
}
else if (op == "empty")
{
if (hh <= tt) cout << "No" << endl;
else cout << "Yes" << endl;
}
else if (op == "query")
{
cout << qu[hh] << endl;
}
}
return 0;
}
单调栈:
问题:
给定一个长度为 N NN 的整数数列,输出每个数左边第一个比它小的数,如果不存在则输出-1
#include<iostream>
using namespace std;
const int N=100010;
int n;
int stk[N],tt;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=0;i<n;i++){
int x;
cin>>x;
while(tt && stk[tt]>=x) tt--;//一直出栈,直到找到第一个比栈顶小的元素
if(tt) cout<<stk[tt]<<" ";//栈不空,直接输出栈顶
else cout<<-1<<' ';//不存在
stk[++tt]=x;//该数入栈
}
return 0;
}
单调队列
#include<iostream>
#include<vector>
using namespace std;
const int N = 10010;
int a[N], q[N];
int hh = -1, tt = -1;
int main()
{
int n, k;
cin >> n >> k;
for (int i = 0; i < n; i++)
{
cin >> a[i];
if (i - k + 1 > q[hh]) ++hh;
while (hh <= tt && a[i] <= a[q[tt]]) --tt;
q[++tt] = i;
if (i + 1 >= k) cout << a[q[hh]];
}
cout << endl;
hh = 0, tt = -1;
for (int i = 0; i < n; i++)
{
if (i - k + 1 > q[hh])++hh;
while (hh <= tt && a[i] >= a[q[tt]]) --tt;
q[++tt] = i;
if (i + 1 >= k) cout << a[q[hh]];
}
return 0;
}