线性表——栈,队列,链表

一.栈

栈(stack)(last in first out);后进先出

1.函数实现栈

#include<cstdio>
using namespace std;
int s[10005];
int tot;
void push(int x)
{
    s[++tot]=x;
}
void pop()
{
    tot--;
}
void print()
{
    for(int i=1;i<=tot;i++)
        printf("%d ",s[i]);
    puts("");
}
void top()
{
    printf("top=%d\n",s[tot]);
}
int main(void)
{
    push(1);
    print();
    top();
    push(2);
    print();
    top();
    push(3);
    print();
    top();
    pop();
    print();
    top();
    pop();
    print();
    top();
    pop();
    print();
    return 0;
}

输出

1
top=1
1 2
top=2
1 2 3
top=3
1 2
top=2
1
top=1

2.宏定义实现栈

int s[10005],tot=0;
#define push(x) s[++tot]=x
#define pop tot--
#define size tot
#define top s[tot];

3.STL实现栈

STL中的stack无法随机访问

#include<stack>
#include<cstdio>
using  namespace std;
stack<int>s;
int main()
{
    s.push(10);
    printf("top=%d\n",s.top());
    s.push(20);
    printf("top=%d\n",s.top());
    s.push(30);
    printf("top=%d\n",s.top());
    printf("size=%d\n",s.size());
    while(!s.empty())
    {
        printf("%d ",s.top());
        s.pop();
    }
    puts("");
    return 0;
}

例题1:P1241 括号序列

P1241 括号序列
题目描述
定义如下规则序列(字符串):
1.空序列是规则序列;
2.如果S是规则序列,那么(S)和[S]也是规则序列;
3.如果A和B都是规则序列,那么AB也是规则序列。
例如,下面的字符串都是规则序列:
(),[],(()),([]),()[],()[()]
而以下几个则不是:
(,[,],)(,()),([()
现在,给你一些由‘(’,‘)’,‘[’,‘]’构成的序列,你要做的,是补全该括号序列,即扫描一遍原序列,对每一个右括号,找到在它左边最靠近它的左括号匹配,如果没有就放弃。在以这种方式把原序列匹配完成后,把剩下的未匹配的括号补全。
输入格式
输入文件仅一行,全部由‘(’,‘)’,‘[’,‘]’组成,没有其他字符,长度不超过100。
输出格式
输出文件也仅有一行,全部由‘(’,‘)’,‘[’,‘]’组成,没有其他字符,把你补全后的规则序列输出即可。
输入输出样例
输入 #1
([()
输出 #1
()
说明/提示
将前两个左括号补全即可。

在这里插入代码片

例题2:P1449 后缀表达式

P1449 后缀表达式
题目描述
所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优先级)。
如:3*(5–2)+7对应的后缀表达式为:3.5.2.-*7.+@。’@’为表达式的结束符号。‘.’为操作数的结束符号。
输入格式
输入:后缀表达式
输出格式
输出:表达式的值
输入输出样例
输入 #1

3.5.2.-*7.+@

输出 #1

16

说明/提示
字符串长度,1000内。

二.队列

队列:first in first out 先入先出

实现队列

int s[10005],fnt,end;
#define push(x) s[++end]=x
#define pop fnt++
#define front s[fnt]
#define size end-fnt+1

例题1.约瑟夫问题

题目描述
n个人(n<=100)围成一圈,从第一个人开始报数,数到m的人出列,再由下一个人重新从1开始报数,数到m的人再出圈,……依次类推,直到所有的人都出圈,请输出依次出圈人的编号.
输入格式
n m
输出格式
出圈的编号
输入输出样例
输入 #1

10 3

输出 #1
3 6 9 2 7 1 8 5 10 4
使用队列来做

#include<queue>
#include<cstdio>
#include<iostream>
using namespace std;
queue<int>q;
int n,k;
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++)
        q.push(i);
    int now=1;
    while(!q.empty())
    {
        if(now==k)
        {
            cout<<q.front()<<" ";
            q.pop();
            now=1;
        }
        else {
            q.push(q.front());//实现环
            q.pop();
            now++;
        }
    }
    cout<<endl;
    return 0;
}

公式法,求最后留下来的人

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=1e6+5;
ll n,k,cnt;
int main()
{
    cin>>n>>k;
    for(ll i=1;i<=n;i++)\
        cnt=(cnt+k)%i;
    cout<<cnt+1<<endl;
    return 0;
}

三.双端队列

#include<stack>
#include<iostream>
using namespace std;
deque<int>d;
int main()
{
    d.push_front(1);//前
    d.push_back(10);//后
    cout<<d.front()<<endl;
    cout<<d.back()<<endl;
    cout<<d[0]<<endl;//支持随机访问(下标访问)但是复杂度很高O(n);
    cout<<d[1]<<endl;
    d.pop_front();
    d.pop_back();
    return 0;
}

输出:

1
10
1
10

链表