面向对象程序设计(荣誉)实验三 算法及list

1.成绩排序(算法与仿函数)

题目描述

N个学生的数据,将学生数据按成绩升序排序,如果成绩相同则按姓名字典升序排序,如果姓名的字母序也相同则按照学生的年龄升序排序,并输出N个学生排序后的信息。

输入

测试数据有多组,直到输入结束

每组输入第一行有一个整数N(N<=1000),接下来的N行包括N个学生的数据。
每个学生的数据包括姓名(长度不超过100的字符串)、年龄(整形数)、成绩(小于等于100的正数)。

输出

输出排序后的学生信息,格式见样例。

样例输入

3
abc 20 99
bcd 19 97
bed 20 97

样例输出

bcd 19 97
bed 20 97
abc 20 99

题解

#include<bits/stdc++.h>

using namespace std;
struct stu {
    string name;
    int old, score;
} s[1005];

int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> s[i].name >> s[i].old >> s[i].score;
    }
    sort(s, s + n, [](stu a, stu b) {
        if (a.score == b.score && a.name == b.name)
            return a.old < b.old;
        if (a.score == b.score)
            return a.name < b.name;
        return a.score < b.score;
    });
    for (int i = 0; i < n; i++) {
        cout << s[i].name << " " << s[i].old << " " << s[i].score << endl;
    }
}



2.筛选法求素数(算法)

题目描述

用埃拉托斯特尼筛法求num之内的素数就是依次把不大于num的平方根的所有素数的倍数剔除。也即首先从2开始,把2的倍数剔除,然后把下一个剩下的最小素数3的倍数剔除,依此类推直到不大于num的平方根,最后剩下的就都是素数。

用stl容器和remove_if算法实现筛选法求素数。

输入

测试次数

每组测试数据一行:正整数num(num>1)

输出

每组测试数据一行,输出1~num之间的所有素数

样例输入

3
10
2
30

样例输出

2 3 5 7
2
2 3 5 7 11 13 17 19 23 29

题解

#include<bits/stdc++.h>

using namespace std;

struct devided_by {
    int d;

    devided_by(int _d) {
        d = _d;
    }

    bool operator()(int n) {
        return n % d == 0 && n != d;
    }
};

void Sieve(int n) {
    vector<int> prime;
    for (int i = 2; i <= n; i++) {
        prime.push_back(i);
    }
    auto end = prime.end();
    for (auto v = prime.begin(); (*v) * (*v) <= n; ++v) {
        end = remove_if(prime.begin(), end, devided_by(*v));
    }

    cout << prime[0];
    for (auto i = prime.begin() + 1; i != end; i++) {
        cout << " " << *i;
    }
    cout << endl;
}

int main() {
    int n, t;
    cin >> t;
    while (t--) {
        cin >> n;
        Sieve(n);
    }
}



3.扑克牌整理(算法与仿函数)

题目描述

扑克牌中有四种花色,从大到小依次为:spade, heart, club, diamond,点数从1到13。小明想将一堆扑克牌中的所有点数大于等于n的某种花色的扑克牌挑出来,并按点数升序排序。请你帮助一下他。

提示:sort 、partition。

输入

测试多组,直到输入结束

每组测试,首先扑克牌张数t,随后输入t张扑克牌花色和点数

接着输入要挑选的次数p

接着输入每次要挑选的扑克牌花色和最小点数n

输出

首先输出挑出来的每张牌

然后输出挑出来的扑克牌数量

样例输入

16
spade 2
spade 13
heart 3
spade 6
club 7
diamond 9
spade 12
heart 10
spade 1
club 2
diamond 8
spade 3
heart 4
spade 11
club 5
diamond 7
2
club 8
diamond 2

样例输出

0
diamond 7
diamond 8
diamond 9
3

题解

#include<bits/stdc++.h>

using namespace std;

struct card {
    string color;
    int num;

    card(string c, int n) : color(c), num(n) {}
};

struct divide_c {
    card cd;

    divide_c(string _col, int _num) : cd(_col, _num) {}

    bool operator()(card &c) {
        return (c.color == cd.color && c.num > cd.num);
    }
};

string ccard;
int nnum;

bool part(card c) {
    return c.color == ccard && c.num >= nnum;
}

int main() {
    int n, q;
    while (cin >> n) {
        string cd;
        int num;
        vector<card> c;
        for (int i = 0; i < n; i++) {
            cin >> cd >> num;
            c.push_back(card(cd, num));
        }
        sort(c.begin(), c.end(), [](card a, card b) { return a.num < b.num; });
        cin >> q;
        while (q--) {
            cin >> cd >> num;
            ccard = cd;
            nnum = num;
            card now = card(cd, num);
            auto end = stable_partition(c.begin(), c.end(), part);
            int cnt = 0;
            for (auto i = c.begin(); i != end; i++) {
                cout << i->color << " " << i->num << endl;
                cnt++;
            }
            cout << cnt << endl;
        }
    }
}



4.前驱后继(list)

题目描述

在双向链表中,A有一个指针指向了后继节点B,同时,B又有一个指向前驱节点A的指针。这样不仅能从链表头节点的位置遍历整个链表所有节点,也能从链表尾节点开始遍历所有节点。

对于给定的一列数据,按照给定的顺序建立双向链表,按照关键字找到相应节点,输出此节点的前驱节点关键字及后继节点关键字。

输入

第一行两个正整数n(代表节点个数),m(代表要找的关键字的个数)。

接下来输入n个整数为关键字key(数据保证关键字在数列中没有重复)。

接下来有m个要查找的关键字,每个占一行。

输出

对给定的每个关键字,输出此关键字前驱节点关键字和后继节点关键字。如果给定的关键字没有前驱或者后继,则不输出。给定关键字为每个输出占一行。

样例输入

10 3
1 2 3 4 5 6 7 8 9 0
3
1
0

样例输出

2 4
2
9

题解

#include<bits/stdc++.h>

using namespace std;

int main() {
    int n, m, x;
    cin >> n >> m;
    list<int> l;
    for (int i = 0; i < n; i++) {
        cin >> x;
        l.push_back(x);
    }
    while (m--) {
        cin >> x;
        for (auto i = l.begin(); i != l.end(); ++i) {
            if (*i == x) {
                if (i != l.begin()) {
                    cout << *(--i);
                    ++i;
                    if ((++i) != l.end()) {
                        cout << " " << *i << endl;
                        --i;
                    } else {
                        cout << endl;
                    }
                } else if ((++i) != l.end()) {
                    cout << *i << endl;
                    --i;
                }
                break;
            }
        }
    }
    return 0;
}

5.线性表操作(list)

题目描述

线性表最基本、最简单、也是最常用的一种数据结构。一个线性表是n个具有相同特性的数据元素的有限序列。用list容器存储m个线性表(m<10),并实现线性表的以下操作。

insert i loc e:在第i个表的第loc位置插入元素e。表位置从1开始,有效插入位置1 ~ 表长+1。

delete i loc : 删除第i表的第loc个元素。

merge i j:使用sort方法对第i,j个表升序排序,再使用merge方法将第j个表合并到第i个表。

unique i : 对第i个表降序排序,使用unique方法删除重复元素。

display i: 输出第i个表元素个数及各元素。

所有操作的表序号i,j输入均合法。位置lco, 元素e均为整数,注意判断插入和删除的位置loc。

输入

第一行:表个数m(>0)

第二行到第m+1行,每行一个表的数据,格式为:数据个数n, 后跟n个整数。

第m+2行:操作次数t,后跟t行,每行一个操作,见题目描述。

输出

对t个操作,分别输出一行,输出操作后的表。具体输出格式见样例。

样例输入

3
10 43 54 23 12 76 -4 53 50 34 10
3 3 243 12
6 3 12 32 42 53 50
7
insert 1 1 15
delete 2 3
merge 2 3
unique 2
display 3
delete 1 1
insert 1 12 200

样例输出

11 15 43 54 23 12 76 -4 53 50 34 10
2 3 243
8 3 3 12 32 42 50 53 243
7 243 53 50 42 32 12 3
0
10 43 54 23 12 76 -4 53 50 34 10
10 43 54 23 12 76 -4 53 50 34 10

题解

#include<bits/stdc++.h>

using namespace std;

int main() {
    int n, m, num;
    cin >> m;
    list<list<int> > l(m);
    for (auto &i : l) {
        cin >> n;
        for (int j = 0; j < n; j++) {
            cin >> num;
            i.push_back(num);
        }
    }
    int q;
    cin >> q;
    for (int i = 0; i < q; i++) {
        string op;
        int pos1, pos2, num;
        cin >> op >> pos1;
        pos1--;
        if (op == "insert") {
            cin >> pos2 >> num;
            pos2--;
            auto i = l.begin();
            advance(i, pos1);
            if (0 <= pos2 && pos2 <= i->size()) {
                auto j = i->begin();
                advance(j, pos2);
                i->insert(j, num);
            }
        }
        if (op == "delete") {
            cin >> pos2;
            pos2--;
            auto i = l.begin();
            advance(i, pos1);
            if (0 <= pos2 && pos2 < i->size()) {
                auto j = i->begin();
                advance(j, pos2);
                i->erase(j);
            }
        }
        if (op == "merge") {
            cin >> pos2;
            pos2--;
            auto i = l.begin(), j = l.begin();
            advance(i, pos1);
            advance(j, pos2);
            i->sort();
            j->sort();
            i->merge(*j);
        }
        if (op == "unique") {
            auto i = l.begin();
            advance(i, pos1);
            i->sort(greater<int>());
            i->unique();
        }

        auto I = l.begin();
        advance(I, pos1);
        cout << I->size();
        for (auto j = I->begin(); j != I->end(); j++) cout << " " << *j;
        cout << endl;
    }
}



6.多项式运算(list)

题目描述

一元多项式按照升幂表示为:

Pn(x) = p0+ p1x + p2x2+ … +pnxn。(n>=0)

用list容器存储一元多项式的系数和指数。输入两个一元多项式,求多项式加、减、乘。

输入

测试次数

每组测试数据两行:

第一行,第一个多项式:项数n 系数1 指数1 系数2 指数2 … 系数n 指数n(按升幂给出)

第二行,第二个多项式:项数n 系数1 指数1 系数2 指数2 …系数n 指数n(按升幂给出)

假设系数为整型。

输出

每组测试数据输出三行,分别是两个多项式的加、减、乘。具体输出格式见样例(即通常多项式表示,注意1,-1的情况。)

样例输入

2
3 -9 0 4 1 -3 5
1 -7 0
2 1 0 -1 3
3 1 0 1 1 -1 2

样例输出

-16+4x-3x^5
-2+4x-3x^5
63-28x+21x^5
2+x-x^2-x^3
-x+x^2-x^3
1+x-x^2-x^3-x^4+x^5

题解

#include<bits/stdc++.h>

#define P pair<int,int>
#define scd second
#define fst first
using namespace std;
vector<int> add, mul, sub;
P nowop;

void Add(P cur) {
    add[cur.scd] += cur.fst;
}

void Sub_1(P cur) {
    sub[cur.scd] += cur.fst;
}

void Sub_2(P cur) {
    sub[cur.scd] -= cur.fst;
}

void Mul(P cur) {
    P nowans;
    nowans.scd = cur.scd + nowop.scd;
    nowans.fst = cur.fst * nowop.fst;
    mul[nowans.scd] += nowans.fst;
}

int main() {
    int t, n1, n2;
    cin >> t;
    while (t--) {
        int value, index, n3;
        cin >> n1;
        n3 = max(n1, n2);
        list<P > l1, l2;
        add.clear();
        mul.clear();
        sub.clear();
        for (int i = 0; i < 100; i++) {
            add.push_back(0);
            sub.push_back(0);
            mul.push_back(0);
        }
        for (int i = 0; i < n1; i++) {
            cin >> value >> index;
            l1.push_back(P(value, index));
        }
        cin >> n2;
        for (int i = 0; i < n2; i++) {
            cin >> value >> index;
            l2.push_back(P(value, index));
        }
        for_each(l1.begin(), l1.end(), Add);
        for_each(l2.begin(), l2.end(), Add);

        for_each(l1.begin(), l1.end(), Sub_1);
        for_each(l2.begin(), l2.end(), Sub_2);


        for (auto i = l1.begin(); i != l1.end(); i++) {
            nowop = *i;
            for_each(l2.begin(), l2.end(), Mul);
        }
        ///print ans//
        int flag = 0;
        for (int i = 0; i < add.size(); i++) {
            if (add[i] == 0) continue;
            if (add[i] != 0 && i == 0) {
                cout << add[0];
                flag = 1;
                continue;
            }
            if (add[i] == -1) cout << "-";
            else if (add[i] > 1) {
                if (flag) cout << "+";
                cout << add[i];
            }
            else if (add[i] == 1) { if (flag) cout << "+"; }
            else if (add[i] != 1) cout << add[i];
            if (i >= 1)cout << "x";
            if (i > 1) cout << "^" << i;
            flag = 1;
        }
        if (flag == 0) cout << 0;
        cout << endl;

        flag = 0;
        for (int i = 0; i < sub.size(); i++) {
            if (sub[i] == 0) continue;
            if (sub[i] != 0 && i == 0) {
                cout << sub[0];
                flag = 1;
                continue;
            }
            if (sub[i] == -1) cout << "-";
            else if (sub[i] > 1) {
                if (flag) cout << "+";
                cout << sub[i];
            }
            else if (sub[i] == 1) { if (flag) cout << "+"; }
            else if (sub[i] != 1) cout << sub[i];
            if (i >= 1)cout << "x";
            if (i > 1) cout << "^" << i;
            flag = 1;
        }
        if (flag == 0) cout << 0;
        cout << endl;

        flag = 0;
        for (int i = 0; i < mul.size(); i++) {
            if (mul[i] == 0) continue;
            if (mul[i] != 0 && i == 0) {
                cout << mul[0];
                flag = 1;
                continue;
            }
            if (mul[i] == -1) cout << "-";
            else if (mul[i] > 1) {
                if (flag) cout << "+";
                cout << mul[i];
            }
            else if (mul[i] == 1) { if (flag) cout << "+"; }

            else if (mul[i] != 1) cout << mul[i];
            if (i >= 1)cout << "x";
            if (i > 1) cout << "^" << i;
            flag = 1;
        }
        if (flag == 0) cout << 0;
        cout << endl;

    }
}



7.约瑟夫环(list)

题目描述

N个人围成一个圆圈,每个人都有唯一的一个编号,编号从1到N,从编号为1的人开始报数,依次报到K,报数为K的人出列,他的下一个又从1开始报数,直到所有的人都出列,求这个出列的序列。

(必须用list)

输入

测试次数t

每次输入n和k

输出

出队序列

样例输入

2
5 3
10 4

样例输出

3 1 5 2 4
4 8 2 7 3 10 9 1 6 5

题解

#include<bits/stdc++.h>

#define P pair<int,int>
using namespace std;

int main() {
    int t, n, k;
    cin >> t;
    while (t--) {
        cin >> n >> k;
        list<int> table;
        vector<int> ans;
        for (int i = 1; i <= n; i++) {
            table.push_back(i);
        }
        auto I = table.begin();
        while (table.size()) {
            for (int i = 0; i < k - 1; i++) {
                I++;
                if (I == table.end()) I++;
            }
            auto died = I;
            I++;
            if (I == table.end()) I++;
            ans.push_back(*died);
            table.erase(died);
        }
        for (int i = 0; i < ans.size(); i++) {
            cout << ans[i] << " \n"[i == ans.size() - 1];
        }
    }
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

上山打老虎D

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值