[温习C/C++]0x05 C++刷题技巧—set自定义排序及查找

系列文章目录

[温习C/C++]0x00-STL标准模板库概述
[温习C/C++]0x01-STL泛型算法-持续更新长文版
[温习C/C++]0x03-sort排序
[温习C/C++]0x04 C++刷题基础编码技巧
[温习C/C++]0x05 C++刷题技巧—set自定义排序及查找

更新日志

日期变更内容
2025-09-07完成初稿

目标

set<Student, MyCompare>集合中, 在按 “年龄不同时按身高升序、年龄相同时按姓名升序” 规则排序的学生集合中,查找并输出第一个不小于(年龄 4、身高 120、姓名 “Abc”)的学生元素。

重载()

#include <iostream>
#include <set>
#include <string>

using namespace std;

struct Student {
    int age;
    int height;
    string name;
    Student(int a, int h, string n): age(a), height(h), name(n) {}
};

class MyCompare {
public:

    bool operator()(const Student& s1, const Student& s2) const { // 这里重要,必须结尾声明成const
        if (s1.age != s2.age) { // 年龄不等的时候
            return s1.height < s2.height; // 身高升序
        }
        return s1.name.compare(s2.name); // 名字升序
    }
};

int main(int argc, char **argv) {
    set<Student, MyCompare> stuSet;
    stuSet.insert(Student(3, 125, "Orage"));
    stuSet.insert(Student(3, 105, "Apple"));
    stuSet.insert(Student(4, 115, "Lemon"));
    stuSet.emplace(4, 106, "Grape");

    auto iter = stuSet.lower_bound(Student(4, 120, "Abc"));
    if (iter != stuSet.end()) {
        cout << iter->age << " " << iter->height << " " << iter->name << endl;
    }
    return 0;
}

  • 排序后结果
    在这里插入图片描述

这段代码的核心功能是在一个自定义排序规则的set容器中,查找第一个不小于(即大于或等于)指定学生对象的元素,具体分析如下:

解析

Student结构体:表示学生对象,包含age(年龄)height(身高)name(姓名)三个属性。

MyCompare比较器:定义了set中元素的排序规则:
若两个学生的age(年龄)不同,则按height(身高)升序排列(s1.height < s2.height);
age相同,则按name(姓名)升序排列(通过string::compare实现,本质是字典序)。
set<Student, MyCompare> stuSet:一个按MyCompare规则排序的集合,存储学生对象。

查找逻辑

代码中通过stuSet.lower_bound(Student(4, 120, "Abc"))进行查找:
lower_boundset的成员函数,功能是返回集合中第一个不小于(即大于或等于)目标值的元素的迭代器(“不小于” 的判断依据是集合的比较器MyCompare)。

目标值是临时构造的学生对象Student(4, 120, "Abc")(年龄 4、身高 120、姓名 “Abc”)。

查找结果分析

结合集合中的元素和排序规则:
集合中的 4 个学生按MyCompare排序后,顺序为:
(3, 105, "Apple")(年龄 3,身高 105)
(3, 125, "Orage")(年龄 3,身高 125)
(4, 105, "Grape")(年龄 4,身高 105)
(4, 115, "Lemon")(年龄 4,身高 115)

MyCompare规则判断 “是否不小于目标(4, 120, “Abc”)”:
前两个元素年龄为 3(与目标年龄 4 不同),比较身高:
第 1 个元素身高 105 < 120 → 小于目标;
第 2 个元素身高 125 > 120 → 不小于目标(满足条件)。

因此,lower_bound返回的是第 2 个元素(3, 125, "Orage")的迭代器,最终输出该元素的信息。

重载<

#include <iostream>
#include <set>
#include <string>

using namespace std;

struct Student {
    int age;
    int height;
    string name;
    Student(int a, int h, string n): age(a), height(h), name(n) {}
    bool operator < (const Student& other) const { // 这里重要,必须结尾声明成const
        if (age != other.age) { // 年龄不等的时候
            return height < other.height; // 身高升序
        }
        return name.compare(other.name); // 名字升序
    }
};

int main(int argc, char **argv) {
    set<Student> stuSet;
    stuSet.insert(Student(3, 125, "Orage"));
    stuSet.insert(Student(3, 105, "Apple"));
    stuSet.insert(Student(4, 115, "Lemon"));
    stuSet.emplace(4, 106, "Grape");

    auto iter = stuSet.lower_bound(Student(4, 120, "Abc"));
    if (iter != stuSet.end()) {
        cout << iter->age << " " << iter->height << " " << iter->name << endl;
    }
    return 0;
}

insert 和 emplace 的使用

emplace对应insert, emplace_back对应于push_back。

但insert和push_back是直接将对象拷贝至容器当中,而emplace和emplace_back是先调用存储对象构造函数,在内存中生成对象,然后拷贝至容器中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值