单链表
如果用结构体表示节点,如下
struct LinkNode{
Elem val;
LinkNode *next;
};
用结构体建立单链表时,比较耗费时间
采用数组模拟单链表,即静态链表,时间效率较高。
e[N],ne[N]分别存储节点的值和下一个节点的下标。
head //头指针
idx //索引节点的下标
初始化操作
void Init(){
head = -1;//head指向空
idx = 0;
}
头插法
void insert_head(int x){
e[idx] = x;
ne[idx] = head;
head = idx++;
}
在k后面插入一个元素
void insert_k(int k,int x){
e[idx] = x;
ne[idx] = ne[k];
ne[k] = idx++;
}
删除操作
//经下标是k的后面的点删掉
void delete(int k){
ne[k] = ne[ne[k]];
}
双链表
定义两个数组:l[N],r[N],同时以下标为0的点为头,下标为1的点为尾。
初始化
void Init(){
r[0] = 1;
l[1] = 0;
idx = 2;//注意0和1已经被用过了
}
在k的右边插入一个元素
void add(int k,int x){
e[idx] = x;
r[idx] = r[k];
l[idx] = k;
l[r[k]] = idx;
r[k] = idx++;
}
//如果在k左边插入,就是在k-1的右边插入。
删除第k个结点
void delete_k(int k){
r[l[k]] = r[k];
l[r[k]] = l[k];
}
栈
栈是一种先进后出的数据结构,相关操作如下
//定义栈
stk[N],tt;//tt表示栈顶
//入栈
stk[++tt] = x;
//出栈
--tt;
//栈是否为空
tt>0?
//栈顶元素
stk[tt]
队列
队列是先进先出的数据结构,相关操作如下
//定义队列
q[N],hh,tt//hh队头,tt=-1队尾,在队尾插入元素,在队头弹出元素。
//插入
q[++tt] = x;
//弹出
hh++;
hh<=tt,非空
单调栈
模板题
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int stk[N],tt;
int n;
int main()
{
scanf("%d",&n);
int x;
for(int i=0;i<n;i++){
scanf("%d",&x);
while(tt&&stk[tt]>=x){
tt--;
}
if(tt) printf("%d ",stk[tt]);
else printf("-1 ");
stk[++tt] = x;
}
return 0;
}
单调队列(滑动窗口问题)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
int a[N],hh,tt;
int q[N];
int n,k;
int main()
{
scanf("%d%d",&n,&k);
hh=0,tt=-1;
for(int i=0;i<n;i++)scanf("%d",&a[i]);
for(int i=0;i<n;i++){
while(hh<=tt&&i-k+1>q[hh]) hh++;//判断窗口大小是否超过
while(hh<=tt&&a[q[tt]]>=a[i]) tt--;
q[++tt] = i;
if(i>=k-1)printf("%d ",a[q[hh]]);
}
printf("\n");
hh=0,tt=-1;
for(int i=0;i<n;i++){
while(hh<=tt&&i-k+1>q[hh]) hh++;
while(hh<=tt&&a[q[tt]]<=a[i]) tt--;
q[++tt] = i;
if(i>=k-1)printf("%d ",a[q[hh]]);
}
return 0;
}