【问题标题】:How to ensure that a std::map is ordered?如何确保 std::map 是有序的?
【发布时间】:2013-01-05 23:54:18
【问题描述】:

使用std::map<int, ...> 如何确保在插入时迭代它会按整数键的升序进行?

【问题讨论】:

标签: c++ stl


【解决方案1】:

你不需要做任何事情。地图将根据键的值升序排列。

在内部,地图在键之间进行比较以对其元素进行排序。默认情况下,它使用std::less<KEY>,相当于bool operator<(int, int) 用于整数。对于用户定义的类型,您必须选择:

  1. 实现 bool operator<(const MyType&, const MyType&) 在用户定义类型之间实现严格的弱排序比较。如果您的类型具有自然顺序,请使用此选项

  2. 提供一个实现严格弱排序的二元仿函数,您可以将其作为第三个模板参数传递给映射。如果您的类型没有自然顺序,或者如果您想使用与 std::less<Key> 使用的顺序不同的顺序构建地图,请使用此选项,通过第 1 点中的bool operator<(...)

通常在幕后发生的事情是 map 实现为自平衡二叉树,并使用严格的弱排序来在 map 中放置新元素,并确定两个元素是否相等。顺便说一句,同样的逻辑适用于std::set,其中键和值是相同的。

【讨论】:

  • 我不明白地图是如何做到的。对于整数键,这很容易,但如果我使用类作为键会发生什么?
  • @sharethis: std::less(至少默认情况下)是这样的。
  • @sharethis 您必须为std::map 提供排序函数(或函数对象)。如果不是,则默认为std::less,而后者又默认使用<。除非您的班级有自然排序(例如 <> 等通常有意义),否则提供排序运算符是最好的解决方案。
  • @Fanael, JamesKanze。现在我了解了std::map 的工作原理。现在说得通了,谢谢!
【解决方案2】:

std::map 自己做。您无需执行任何操作。

默认情况下,它按升序对键进行排序。如果您希望它按降序排序,则将 std::greater<T> 作为 third 模板参数传递给 std::map

std::map<int, X>  m1;                    //sorts key in increasing order
std::map<int, X, std::greater<int>>  m2; //sorts key in decreasing order
std::map<int, X, std::less<int>> m3;     //sorts key in increasing order

third template parameter默认 参数是 std::less&lt;T&gt;,所以上面的 m1m3 是相同的类型!

演示:

#include <iostream>
#include <map>
#include <string>

int main()
{
    std::cout << "\nkeys are in increasing order: \n";
    std::map<int, std::string> m1;
    m1[5] = "first insertion but higher key";
    m1[1] = "second insertion but lower key";
    for(auto const & item : m1) 
       std::cout << "{" << item.first  <<"," << item.second << "}\n";

    std::cout << "\nkeys are in decreasing order: \n";   
    std::map<int, std::string, std::greater<int> > m2;
    m2[1] = "first insertion but lower key";
    m2[2] = "second insertion but higher key";
    for(auto const & item : m2) 
       std::cout << "{" << item.first  <<"," << item.second << "}\n";
}

输出:

keys are in increasing order: 
{1,second insertion but lower key}
{5,first insertion but higher key}

keys are in decreasing order: 
{2,second insertion but higher key}
{1,first insertion but lower key}

请注意,在这两种情况下,项目都按照std::map 的第三个模板参数指定的顺序排列。输出不依赖于插入的顺序,而是键的顺序!

Live demo

还有std::unordered_map 不对元素进行排序。

【讨论】:

  • 小优化,这也是 clang-tidy 现代化检查的一部分:您应该透明地定义它们 ;) std::map&lt;int, X, std::greater&lt;&gt;&gt;
【解决方案3】:

map 通常实现为binary search tree,因此迭代器已经为您提供了排序的键。

如果您不关心订单,您可以使用unordered_map(来自 c++11 或 boost),这可以让您加快订单交易。

【讨论】:

  • 它不必实现为树。它只需要订购,并满足一定的复杂性限制。搜索树可以做到这一点,其他各种数据结构也是如此。
  • 这仍然暗示元素是否按key排序可能取决于实现方式,这是错误的;按键排序是一项要求,而不仅仅是(最常见的)实现的细节。
猜你喜欢
  • 1970-01-01
  • 2015-01-31
  • 1970-01-01
  • 2012-07-01
  • 1970-01-01
  • 2015-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多