2、数据结构
2.1、单链表:主要用作邻接表(存储图、树)
使用数组模拟单链表:
const int N = 100010;
// head存储链表头,
//e[]存储节点的值,
//ne[]存储节点的next指针,
//idx表示当前节点
int head, e[N], ne[N], idx;
//初始化
void init(){
head = -1;
idx = 0;
}
//将x插入到头结点
void add_to_head(int x){
e[idx] = x;
ne[idx] = head;
head = idx;
idx ++;
}
//将x插入到下标为 k 的后面
void add(int k, int x){
e[idx] = x;
ne[idx] = ne[k];
ne[k] =idx;
idx++;
}
//将第k个数(下标为 k-1)删除
void remove(int k){
ne[k] = ne[ne[k]];
}
2.2、双链表:优化某些问题
const int N =100010;
//e[]存储节点的值,
//l[]存储节点的左指针,
//r[]存储节点的右指针,
//idx表示当前节点
int e[N], l[N], r[N], idx;
void init(){
// 0表示左端点,1表示右端点
r[0] = 1, l[1] = 0;
idx =2;
}
//在下标是K的右边插入一个
//在下标为k的左边一个插入一个数 调用 add(l[k],x)即可
void add(int k, int x){
e[idx] = x;
r[idx] = r[k];
l[idx] = k;
l[r[k]] = idx;
r[k] = idx;
idx++;
}
//删除下标为 k 的数
void remove(int k){
r[l[k]] = r[k];
l[r[k]] = l[k];
}
2.3、栈
用top表示栈顶所在的索引。
初始时,top = -1。表示没有元素。
pusn x :栈顶所在索引往后移动一格,然后放入x。st[++top] = x。
pop : top 往前移动一格。top–
empty :top 大于等于 0 栈非空,小于 0 栈空。top == -1 ? “YES” : “NO”
query : 返回栈顶元素。st[top]
#include <iostream>
using namespace std;
const int N = 100010;
int stack[N], top = -1;
/*
//插入
stk[++ top] = x;
//弹出
top--;
//判断栈是否为空
if(top> 0) not empty;
else empty;
//栈顶
stk[top];
*/
int main(){
int m;
cin>> m;
while(m--){
string op;
int x;
cin >> op;
if(op =="push"){
cin>>x;
stack[++top] = x;
}else if( op == "pop"){
--top;
}else if( op == "empty"){
if(top > 0)
cout << "NO" <<endl;
else
cout << "YES" <<endl;
}else{
cout << stack[top]<< endl;
}
}
return 0;
}
2.4、队列
数组模拟普通队列:
#include <iostream>
using namespace std;
const int N = 100010;
// hh 表示队头,tt表示队尾
int q[N], hh = 0, tt = -1;
int main(){
int m;
cin>> m;
while(m--){
string op;
int x;
cin >> op;
if ( op == "push") {
cin >> x;
q[++tt = x;]
}else if ( op == "pop") {
hh++;
}else if ( op == empty) {
cout<<(hh>tt?"YES":"NO")<<endl;
}else {
cout<<q[hh]<<endl;
}
}
return 0;
}
循环队列
// hh 表示队头,tt表示队尾的后一个位置
int q[N], hh = 0, tt = 0;
// 向队尾插入一个数
q[tt ++ ] = x;
if (tt == N) tt = 0;
// 从队头弹出一个数
hh ++ ;
if (hh == N) hh = 0;
// 队头的值
q[hh];
// 判断队列是否为空
if (hh != tt)
{
}
STL中的queue
#include<iostream>
#include<queue>
using namespace std;
const int N=100010;
int n;
int main(){
queue <int> q;
cin>>n;
while(n--){
string op;
int x;
cin>>op;
if(op=="push"){
cin>>x;
q.push(x);
}
else if(op=="pop")
q.pop();
else if(op=="empty")
cout<<(!q.empty()?"NO":"YES")<<endl;
else
cout<<q.front()<<endl;
}
return 0;
}
单调栈:找出每个数左边离它最近的比它大/小的数

#include <iostream>
using namespace std;
const int N = 100010;
int n;
int stack[N], tt; //tt为零时 栈为空
int main(){
cin>> n;
for(int i = 0; i < n; i++){
int x;
cin>> x;
while( tt && stack[tt] >= x) tt--;
if(tt)
cout<< stack[tt] << " ";
else
cout << -1 <<" ";
stack[++tt] = x;
}
return 0;
}
单调队列 :找出滑动窗口中的最大值/最小值


#include <iostream>
using namespace std;
const int N = 100010;
int n, k;
//a作为 原数组 q作为队列 存放 下标
int a[N], q[N];
int main(){
scanf("%d%d",&n, &k);
for(int i = 0; i < n; i++) scanf("%d",&a[i]);
int hh = 0, tt = -1;
for(int i = 0; i < n; i++){
//hh > tt 队列为空 ,当队列不为空,且 队头元素 在当前窗口内
if(hh <= tt && q[hh]<i-k+1 )
hh++; //判断队头前元素 是否在当前窗口内 ,如果不在,也要删除
//当队列不为空 且当前a[i] 小于队列中的数,出队
while( hh <=tt && a[q[tt]]>= a[i])
tt--; //从队尾出队
q[++tt] = i; //入队
if( i >= k - 1)
cout<<a[q[hh]]<<" ";
}
puts("");
hh = 0, tt = -1;
for(int i = 0; i < n; i ++) {
if(hh <= tt && q[hh]<i-k+1 )
hh++;
while( hh <=tt && a[q[tt]] <= a[i])
tt--; //从队尾出队
q[++tt] = i; //入队
if( i >= k - 1)
cout<<a[q[hh]]<<" ";
}
return 0;
}
kmp字符串匹配:
#include<iostream>
using namespace std;
const int N = 100010;
const int M = 1000010;
char p[N];
char s[M];
int n, m;
int ne[N];
int main(){
cin>> n >> p + 1 >> m >> s + 1;
//求模式串的next数组:
for( int i =2, j = 0; i <= n; i++ ){
while( j && p[i] != p[j+1]) j = ne[j];
if(p[i] == p[j+1]) j++;
ne[i]=j;
}
//匹配
for(int i = 1, j = 0; i <= m; i++){
while(j && s[i]!= p[j+1]) j = ne[j];
if(s[i] == p[j+1]) j++;
if( j == n ){
cout << i-n<<" ";
j = ne[j];
}
}
return 0;
}

692

被折叠的 条评论
为什么被折叠?



