算法日记 | C++ 结构体

算法日记 | C++ 结构体实战:如何优雅地处理"复杂数据"?

👋 大家好。

今天我们来点轻松但同样重要的基础内功------ 结构体 (Struct)

很多同学写代码时,还在用 a[100], b[100], c[100] 这样散乱的数组来存数据吗?一旦数据多了,是不是经常搞混哪个数组对应哪个属性?🤯

别慌!今天我们就通过三道洛谷的经典题目(P5740、P5744、P5741),手把手教你如何用 struct 把数据"打包"管理,让代码瞬间变得整洁又强大!🚀

准备好了吗?让我们开始今天的"打包"之旅吧!🎒


🌟 关卡一:寻找"卷王"之王

首先登场的是我们的热身题:P5740【深基 7.例 9】最厉害的学生

🤔 题目大意

班里有 N 个同学,每个人都有姓名、语文、数学、英语成绩。我们需要找出总分最高的那个"学霸"。如果有并列第一,就选名单里排在最前面的那个。

💡 为什么用结构体?

想象一下,如果你不用结构体,你可能需要开四个数组:

  • string names[1000]

  • int chinese[1000]

  • ...

如果要排序,你得动其中一个数组,其他三个也得跟着换位置,简直是灾难现场!💥 而有了结构体,我们只需要把它们"打包"在一起。

💻 核心代码解析

cpp 复制代码
// 定义结构体,把相关数据绑在一起
struct student{
    string name;
    int chinese, math, english;
    int score; // 总分
};

// 自定义比较函数:按分数从高到低排
bool f(const student& a, const student& b){
    return a.score > b.score;
}

int main(){
    vector<student> s;
    int n;
    cin >> n;
    while(n--){
        student temp;
        cin >> temp.name >> temp.chinese >> temp.math >> temp.english;
        temp.score = temp.chinese + temp.math + temp.english; // 算出总分
        s.push_back(temp);
    }

    // 关键点:使用 stable_sort 保持相对顺序
    stable_sort(s.begin(), s.end(), f);

    // 输出第一名
    cout << s.begin()->name << " "
         << s.begin()->chinese << " "
         << s.begin()->math << " "
         << s.begin()->english << endl;

    return0;
}

🧐 避坑指南

注意看这里我用的是 stable_sort 而不是普通的 sort

题目要求:"如果总分相同,输出靠前的那位"。普通的 sort 可能会打乱原本输入的顺序,而 stable_sort 能保证在分数相同时,先输入的依然排在前面。这就是细节决定成败!😎


🌟 关卡二:培训机构的"成长"记录

搞定了排序,我们来看看数据的动态变化。第二题是 P5744【深基 7.习 9】培训

🤔 题目大意

有一批学员参加培训,经过一年后:

  1. 每个人都长了一岁(年龄 +1)。

  2. NOIP 成绩提高了 20%(但是满分 600,不能超过哦)。

我们需要输入原来的信息,输出培训后的新信息。

💡 核心考点:结构体的遍历与计算

这道题不需要复杂的排序,重点在于如何优雅地处理每一个学生的数据更新。看看我的解法,我使用了迭代器(Iterator)来遍历整个班级:

cpp 复制代码
for(vector<student>::iterator it = s.begin(); it != s.end(); it++){
    // 姓名不变,直接输出
    cout << it->name << " ";
    // 年龄自动加 1
    cout << it->year + 1 << " ";
    // 成绩提升 20%,但要注意上限 600
    if(it->score * 1.2 > 600)
        cout << 600 << endl;
    else
        cout << it->score * 1.2 << endl;
}

⚠️ 细节决定成败

这里有个小坑!题目说了成绩不能超过 600。虽然乘以 1.2 很简单,但我们必须加上一个 if 判断来进行"截断"。编程不仅要算得对,还要符合现实世界的规则!


🌟 关卡三:谁是"旗鼓相当"的对手?

最后一题稍微有点难度:P5741【深基 7.例 10】旗鼓相当的对手 - 加强版

🤔 题目大意

如果有两个学生,他们的语文、数学、英语分差都不超过 5 分,且总分差不超过 10 分,那他们就是"旗鼓相当的对手"。请找出所有这样的组合。

💡 核心思路:双重循环暴力匹配

这道题的数据范围N<=1000 ,我们可以放心地使用双重循环来两两比较。

cpp 复制代码
// 判断是否为对手的函数
bool isRival(const student& s1, const student& s2){
    if(abs(s1.a - s2.a) <= 5 &&
       abs(s1.b - s2.b) <= 5 &&
       abs(s1.c - s2.c) <= 5 &&
       abs(s1.score - s2.score) <= 10)
        returntrue;
    else
        returnfalse;
}

int main(){
    // ... 输入部分省略 ...

    // 双重循环查找
    for(int i = 0; i < s.size(); i++){
        for(int j = i + 1; j < s.size(); j++){
            // 只比较后面的,避免重复输出 (A,B) 和 (B,A)
            if(isRival(s[i], s[j])){
                cout << s[i].name << " " << s[j].name << endl;
            }
        }
    }
    return0;
}

🔍 为什么这样写?

  1. 封装判断逻辑 :我把判断条件写在了 isRival 函数里,主函数看起来就非常清爽。

  2. 去重技巧 :内层循环从 j = i + 1 开始。这意味着我们只拿第 个人和他后面的人比。这样既不会自己和自己比,也不会出现"A和B是对手,B和A也是对手"的重复情况。


📝 总结一下

今天我们通过三道题,掌握了结构体的三大用法:

  1. P5740 :利用结构体进行整体排序 (记得 stable_sort)。

  2. P5744 :利用结构体进行批量数据处理(遍历修改)。

  3. P5741 :利用结构体进行对象间的关系匹配(双重循环)。

如果你觉得这篇文章对你有帮助,欢迎点赞、在看、转发三连支持一下!你的鼓励是我更新的最大动力!❤️


相关推荐
笨鸟先飞的橘猫14 小时前
skynet——服务发现学习
学习·服务发现
xier_ran15 小时前
【infra之路】从“三堵叹息之墙”到异构计算的狂飙
开发语言·c++·算法
头歌实践平台15 小时前
LL(1)文法分析
算法
计算机安禾15 小时前
【算法分析与设计】第6篇:动态规划的原理:最优子结构与重叠子问题
算法
Larcher15 小时前
数组去重算法:理论与实践深度解析
javascript·算法·代码规范
CS创新实验室15 小时前
数据结构和算法:摊还分析
java·数据结构·算法
curry____30315 小时前
邻接矩阵 和 领接表 和 链式前向星对比
数据结构·c++·算法
通信小呆呆15 小时前
维度分数傅里叶时频图 + 图神经网络:突破传统时频分析的目标识别与杂波抑制新框架
人工智能·神经网络·算法
大连好光景15 小时前
Skills索引大全
学习·ai编程