如何在C++中声明一组pair的比较器?
在C++中,pair
是用于存储两个值的标准库模板类,来自<utility>
头文件。但是,有时候我们需要在使用pair
时按照一定的规则进行比较,这就需要声明一组比较器。下面将介绍如何在C++中声明一组pair的比较器。
pair的比较方式
在使用pair之前,我们需要了解pair的比较方式。pair的比较方式与元素的类型有关,如下所示:
- 当
pair.first
可以进行小于比较时,pair可以进行小于比较。 - 当
pair.first
小于另一个pair的first
时,pair小于另一个pair。 - 当
pair.first
与另一个pair的first
相等且pair.second
小于另一个pair的second
时,pair小于另一个pair。
因此,我们可以看到,在C++中比较pair对象,优先比较pair.first
,如果相等再比较pair.second
。
pair比较器的声明
当我们需要指定一组比较器来对pair对象进行排序或查找操作时,可以使用STL提供的std::pair_compare<T>
结构体。该结构体可以被视为一个函数对象,支持status_free、function指针等过载函数,可以被传递给STL容器算法中的比较器参数。
下面是一个声明比较器的例子,针对以pair<int, string>
为元素的vector
进行按照第一个元素降序排列:
#include <vector>
#include <utility>
#include <algorithm>
bool compare(const std::pair<int, std::string>& p1, const std::pair<int, std::string>& p2)
{
return p1.first > p2.first;
}
int main()
{
std::vector<std::pair<int, std::string>> v{ {3, "hello"}, {1, "world"}, {2, "bye"} };
std::sort(v.begin(), v.end(), compare);
for (auto& i : v)
std::cout << i.first << " " << i.second << std::endl;
return 0;
}
在声明compare
函数时,我们需要按照STL的Compare规范,在参数列表中声明两个输入参数:指向pair
的指针或引用。函数体中,我们根据排列需求返回true
或false
。
上述代码中,我们将pair
的第一个元素作为排序关键字,使用std::sort()
对vector进行按照第一个元素降序排列,最终输出结果如下:
3 hello
2 bye
1 world
因此,我们可以看到,在进行pair排列操作时,我们只需要根据需求声明相应的比较器即可。
通过lambda表达式声明pair比较器
除了可以使用函数来声明pair比较器之外,还可以使用lambda表达式来声明。
#include <vector>
#include <utility>
#include <algorithm>
int main()
{
std::vector<std::pair<int, std::string>> v{ {3, "hello"}, {1, "world"}, {2, "bye"} };
std::sort(v.begin(), v.end(), [](const auto& p1, const auto& p2) {
return p1.first > p2.first;
});
for (auto& i : v)
std::cout << i.first << " " << i.second << std::endl;
return 0;
}
在上述代码中,我们使用一个lambda表达式来声明一个比较器。在括号中,我们声明了两个输入参数p1
和p2
,并根据要求比较它们的第一个元素。输出结果与前一个例子类似。
不同STL容器中pair的比较方法
在不同的STL容器中,pair的比较方法稍有不同。下面以set
和map
为例说明:
set
在set
中,要按照一定的规则对pair进行比较,我们可以在声明set时,指定一个比较器来进行排序。默认情况下,set会对pair进行键值比较,以pair中的第一个元素作为键值。
#include <set>
#include <utility>
int main()
{
std::set<std::pair<int, std::string>> s;
s.insert({ 3, "hello" });
s.insert({ 1, "world" });
s.insert({ 2, "bye" });
for (auto& i : s)
std::cout << i.first << " " << i.second << std::endl;
return 0;
}
在上述代码中,我们声明了一个set
,并将三个pair对象插入到其中。由于默认情况下set按照pair的第一个元素进行排序,因此输出结果如下:
1 world
2 bye
3 hello
如果我们需要按照pair的第二个元素进行排序,可以自定义比较器:
#include<set>
#include<utility>
#include<algorithm>
struct pair_comparer
{
bool operator() (const std::pair<int, std::string>& p1, const std::pair<int, std::string>& p2) const
{
return p1.second > p2.second;
}
};
int main()
{
std::set<std::pair<int, std::string>, pair_comparer> s;
s.insert({ 3, "hello" });
s.insert({ 1, "world" });
s.insert({ 2, "bye" });
for (auto& i : s)
std::cout << i.first << " " << i.second << std::endl;
return 0;
}
在上述代码中,我们自定义了一个pair_comparer
结构体,并在其中定义了一个成员函数operator()
,实现按照pair的第二个元素进行排序。在声明set
时,我们将这个结构体作为第二个模板参数传递进去,标记该set需要按照pair_comparer
进行排序。最终输出结果如下:
2 bye
3 hello
1 world
map
与set
相似,我们也可以对map
中的pair进行按照键值排序。默认情况下,map
以pair的第一个元素作为键值,因此不需要特定的比较器。
#include <map>
#include <utility>
int main()
{
std::map<std::pair<int, std::string>, double> m;
m.insert({ {3, "hello"}, 1.2 });
m.insert({ {1, "world"}, 3.4 });
m.insert({ {2, "bye"}, 5.6 });
for (auto& i : m)
std::cout << i.first.first << "," << i.first.second << "," << i.second << std::endl;
return 0;
}
在上述代码中,我们声明了一个map
,并将三个pair对象作为键值对插入到其中。由于默认情况下map按照pair的第一个元素进行排序,因此输出结果如下:
1,world,3.4
2,bye,5.6
3,hello,1.2
如果我们需要按照pair的第二个元素进行排序,可以使用一个自定义的比较器:
#include <map>
#include <utility>
struct pair_comparer
{
bool operator() (const std::pair<int, std::string>& p1, const std::pair<int, std::string>& p2) const
{
return p1.second > p2.second;
}
};
int main()
{
std::map<std::pair<int, std::string>, double, pair_comparer> m;
m.insert({ {3, "hello"}, 1.2 });
m.insert({ {1, "world"}, 3.4 });
m.insert({ {2, "bye"}, 5.6 });
for(auto& i : m)
std::cout << i.first.first << "," << i.first.second << "," << i.second << std::endl;
return 0;
}
在上述代码中,我们自定义了一个pair_comparer
结构体,并在其中定义了一个成员函数operator()
,实现按照pair的第二个元素进行排序。在声明map
时,我们将这个结构体作为第三个模板参数传递进去,标记该map需要按照pair_comparer
进行排序。最终输出结果如下:
2,bye,5.6
1,world,3.4
3,hello,1.2
结论
在C++中,声明一组pair的比较器是很有用的,可以用于对pair进行排序或者查找操作。我们可以使用自定义的比较器或者lambda表达式来声明,也可以在每个STL容器中使用不同的比较器进行排序。掌握了这些技巧,我们将能更加灵活地使用pair类型,并优雅地完成各种C++任务。