ch1(数据结构篇)——单链表、双链表、栈、队列、单调栈、单调队列

1.自然语言描述
①单链表:这里使用的是不带头结点的单链表,由一个指向第一个结点的head指针,e数组(e[i]表示第i个插入列表的结点)ne数组(ne[i]表示第i个插入链表的结点的邻接结点)idx表示下一次插入结点的序号。

②双链表:在单链表的基础上加入了每个结点左邻接的结点数组。

③栈:先进后出表,用数组模拟,tt表示栈顶。

④队列:先进先出表,用数组模拟,hh表示队首,tt表示队尾。

⑤单调栈:不断pop栈输出直到栈空,如果得到单调递增序列则为单调递增栈,反之为单调递减栈。对于一个序列,为了找出序列中每一个元素左边第一个比它小的元素,可以用单调递减栈作为数据结构。

⑥单调队列:和单调栈类似,最典型的应用是滑动窗口问题。

2.代码

Acwing 830. 单调栈

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int MAXN=1e5+10;

int skt[MAXN],tt;

int main(void)
{
    
    
    int n;
    cin>>n;
    
    for(int i=0;i<n;i++){
    
    
        
        int x;
        cin>>x;
        //每插入一个数,判断栈顶元素是否大于等于它,如果成立,则出栈。
        //这使得栈顶始终是之前出现过的第一个小于当前数的元素。
        while(tt&&skt[tt]>=x) tt--;
        
        if(tt) cout<<skt[tt]<<' ';
        else cout<<"-1"<<' ';
        
        skt[++tt]=x;
    }
    cout<<endl;
    
    for(int i=1;i<=tt;i++)
        cout<<skt[i]<<' ';
    
    return 0;
}

Acwing 154.滑动窗口

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int MAXN=1e6+10;

int q[MAXN],a[MAXN];
int n,k;

int main(void)
{
    
    
    scanf("%d%d",&n,&k);
    
    for(int i=0;i<n;i++)
        scanf("%d",&a[i]);
        
    //find the minnum
    int hh=0,tt=-1;
    for(int i=0;i<n;i++){
    
    
        //找最小值,则要维护一个递增的队列,使新加入的元素成为队尾,剔除掉之后所有大于等于它的元素。
        //因为若新加入的值比队头小,则滑动窗口队列中应只保留它,反之则说明它不是最小的,但要剔除掉所有比它大的元素,并把它作为队尾。
        //这样比暴力的效率要高很多
        if(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");
    
    //fint the maxnum
    hh=0,tt=-1;
    for(int i=0;i<n;i++){
    
    
        
        if(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;
}

おすすめ

転載: blog.csdn.net/qq_43579980/article/details/114260054