【PAT】栈,队列,链表

PAT1051

梦回编译原理实验

#include <iostream>
#include <stack>

using namespace std;
int main() {
    int M, N, K; // 栈的容量,序列大小,序列数
    stack<int> s;
    int n1; 
    int flag;

    cin >> M >> N >> K;
    int n2[N];

    for (int i = 0; i < K; i++) {
        n1 = 1;
        flag = 1;
        int j = 0;

        for (int j = 0; j < N; j++) {
            cin >> n2[j];
        }
        
        while (j < N) {
            if (!s.empty() && s.top() == n2[j]) {
                s.pop();
                j++;
            } else if ((n1 <= n2[j]) && (s.size() < M)) {
                s.push(n1);
                n1++;
            } else {
                flag = 0;
                break;
            }
        }

        if (flag == 1) {
            cout << "YES" << endl;
        } else {
            cout << "NO" << endl;
        }

        while (!s.empty()) {
            s.pop();
        }
    }
}

队列

PAT1056

最看不懂题目的一集。。完全抄的晴神的《上机训练》。

#include <iostream>
#include <queue>
#include <cmath>
#define MAXN 1010

using namespace std;

// 重量和排名绑在一起,这样就不用考虑对应的关系了
struct mouse {
    int weight; // 重量
    int rank; // 排名
}mouse[MAXN];

int main () {
    int Np, Ng; // 编程者的数量,一组中老鼠数量的最大数
    cin >> Np >> Ng;
    queue<int> q; 

    for (int i = 0; i < Np; i++) {
        cin >> mouse[i].weight;
    }

    int idx;
    for (int i = 0; i < Np; i++) {
        cin >> idx;
        q.push(idx); // 只需要压入老鼠的顺序即可
    }

    double count; // 记录当前轮数有多少只老鼠
    int groups; // 记录当前轮数的老鼠组数
    int maxW;
    int maxIdx;
    while (q.size() > 1) {
        count = q.size();
        groups = ceil(count * 1.0 / Ng);
        // cout << count << " " << groups << " ";
        for (int i = 0; i < groups; i++) { // 当前轮
            maxW = -1;
            for (int j = 0; j < Ng; j++) { // 当前组
                if (count > 0) { // 最后一组老鼠数量可能不满Np
                    idx = q.front();
                    // 每轮未晋级的老鼠排名相同,根据样例看,没有第四名老鼠,因此可以推断(好怪-。-):
                    // 每组晋级一只老鼠,当前轮晋级老鼠数等于组数,因此此轮未晋级的老鼠排名为group+1
                    mouse[idx].rank = groups + 1;
                    q.pop();
                    if (maxW < mouse[idx].weight) { // 选出最大的作为赢家
                        maxIdx = idx;
                        maxW  = mouse[idx].weight;
                    }
                    count --;
                }
            }
            q.push(maxIdx);
        }
    }

    mouse[q.front()].rank = 1;

    for (int i = 0; i < Np; i++) {
        cout << mouse[i].rank;
        if (i != Np - 1) cout << " ";
    }
}

链表

PAT1074

一开始脑洞奇怪写了这个↓完全用链表的思想写的,很麻烦,得分22/25,最后两个一个段错误,一个超时。没有正确理解addr,addr可以是数组下标,所以正确方法应该是开一个100000>的数组。
以及这道题的坑点在于,有些节点可能是无效结点,比如:

00000 6 3
00000 1 11111
11111 2 22222
22222 3 -1
33333 4 44444
44444 5 55555
55555 6 -1
到结点三就输入完毕了,后面的4 5 6是无效结点

#include <iostream>
#include <string>

using namespace std;
struct node {
    int data;
    string addr;
    string next;
    int nextIdx;
};

int main() {
    int N, K; // 结点数量,需要反转的结点数量
    string head;
    int headIdx;
    cin >> head >> N >> K;
    node list[N];
    int num = N; // 有效结点数量

    for (int i = 0; i < N; i++) {
        cin >> list[i].addr >> list[i].data >> list[i].next;
        if (head == list[i].addr) headIdx = i;
    }

    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            if (list[i].next == list[j].addr) {
                list[i].nextIdx = j;
            }
        }
    }

    // 倒转链表
    int t, p = headIdx, q = headIdx, h = headIdx; // p指当前结点,q指当前倒转链表的最后一个结点
    int count = N / K;
    for (int i = 0; i < count; i++) {
        for (int j = 0; j < K - 1; j++) {
            p = list[q].nextIdx;
            list[q].nextIdx = list[p].nextIdx;
            list[q].next = list[p].next;
            list[p].nextIdx = h;
            list[p].next = list[h].addr;
            h = p;
        }
        if (i == 0) {
            headIdx = h;
        }
        else {
            list[t].next = list[h].addr;
            list[t].nextIdx = h;
        }
        if (list[q].next == "-1") {
            num = (i + 1) * K;
            break;
        }
        t = q;
        h = list[q].nextIdx;
        q = h;
        p = h;
    }

    int idx = headIdx;
    for (int i = 0; i < num; i++) {
        cout << list[idx].addr << " " << list[idx].data << " " << list[idx].next << endl;
        idx = list[idx].nextIdx;
    }
}

看了网上的还有这个简单的↓,使用reverse,虽然我感觉这已经不是链表的思想了。启发是有些链表的题用数组模式存储可以简化实现。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;
struct node {
    int data;
    int next;
}list[100010];

int main() {
    int head, N, K; // 结点数量,需要反转的结点数量
    list[100010];
    cin >> head >> N >> K;

    int addr;
    for (int i = 0; i < N; i++) {
        cin >> addr >> list[addr].data >> list[addr].next;
    }

    // 存地址
    vector<int> v;
    for (int i = head; i != -1; i = list[i].next) {
        v.push_back(i);
    }

    // 逆序
    for (int i = 0; i < v.size() / K; i++) {
        reverse(v.begin() + K * i, v.begin() + K * (i + 1));
    }

    for (int i = 0; i < v.size(); i++) {
        printf("%05d %d ", v[i], list[v[i]].data);
        if (i == v.size() - 1) printf("-1");
        else printf("%05d\n", v[i+1]);
    }
    
}

PAT1032

这题好简单,开心一秒,畅想考试的时候遇到这么简单的(

#include <iostream>
#include <string>
#define MAXV 100010

using namespace std;

struct node {
    string data;
    int next;
}list[MAXV];

int main() {
    int h1, h2, N;

    cin >> h1 >> h2 >> N;

    int idx;
    for (int i = 0; i < N; i++) {
        cin >> idx >> list[idx].data >> list[idx].next;
    }

    int len1 = 0, len2 = 0;
    for (int i = h1; i != -1; i = list[i].next) {
        len1++;
    }

    for (int i = h2; i != -1; i = list[i].next) {
        len2++;
    }

    int p = h1, q = h2;
    while (p != -1 && q != -1) {
        if (p == q) {
            printf("%05d", p);
            return 0;
        }
        if (len1 > len2) {
            len1 --;
            p = list[p].next;
        } else if (len1 < len2) {
            len2 --;
            q = list[q].next;
        } else {
            p = list[p].next;
            q = list[q].next;
        }
    }

    printf("-1");
}

PAT1052

这题也很简单,就是无效结点不讲武德= =

#include <iostream>
#include <vector>
#include <algorithm>
#define MAXV 100000

using namespace std;

struct node {
    int data;
    int next;
    int addr;
} list[MAXV];

bool cmp (node n1, node n2) {
    return n1.data < n2.data;
}

int main() {
    int N, h;
    cin >> N >> h;

    int addr;
    for (int i = 0; i < N; i++) {
        cin >> addr >> list[addr].data >> list[addr].next;
        list[addr].addr = addr;
    }

    vector<node> v;
    node n;
    for (int i = h; i != -1; i = list[i].next) {
        v.push_back(list[i]);
    }

    if (v.size() == 0) { // 无效结点,好坑= =
        printf("0 -1");
        return 0;
    }
    
    sort(v.begin(), v.end(), cmp);

    printf("%d %05d\n", v.size(), v[0].addr);
    for (int i = 0; i < v.size(); i++) {
        printf("%05d %d ", v[i].addr, v[i].data);
        if (i == v.size() - 1) printf("-1");
        else printf("%05d\n", v[i+1].addr); 
    }
}

PAT1097

空间换时间,而且简化代码

#include <iostream>
#include <vector>
#include <cmath>
#define MAXV 100010
#define MAX 10010

using namespace std;

struct node {
    int key;
    int next;
} list[MAXV];

int main () {
    int h, N;
    cin >> h >> N;

    int addr;
    for (int i = 0; i < N; i++) {
        cin >> addr >> list[addr].key >> list[addr].next;
    }

    vector<int> v1;
    vector<int> v2;
    int flag[MAX] = {0};
    for (int i = h; i != -1; i = list[i].next) {
        if (flag[abs(list[i].key)]) {
            v2.push_back(i);
        } else {
            v1.push_back(i);
            flag[abs(list[i].key)] = 1;
        }
    }
    
    for (int i = 0; i < v1.size(); i++) {
        printf("%05d %d ", v1[i], list[v1[i]].key);
        if (i == v1.size() - 1) printf("-1\n");
        else printf("%05d\n", v1[i+1]);
    }

    for (int i = 0; i < v2.size(); i++) {
        printf("%05d %d ", v2[i], list[v2[i]].key);
        if (i == v2.size() - 1) printf("-1\n");
        else printf("%05d\n", v2[i+1]);
    }
}
  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值