【问题标题】:Order in std::set and difference to std::unordered_set在 std::set 中排序和与 std::unordered_set 的区别
【发布时间】:2014-09-18 16:51:01
【问题描述】:

我希望std::set 的顺序与std::liststd::vector 一样,只是不会再次附加一个值。 MSVC 110 证明我错了。我希望下面的代码产生下面显示的结果,在 ideone (http://ideone.com/e47GwQ) 上运行代码时就是这种情况(但不确定他们使用的是哪个编译器和版本)。

#include <iostream>
#include <set>

template <typename C>
int insert_get_index(C& container, typename C::value_type value)
{
    typename C::iterator it = container.insert(value).first;
    return std::distance(container.begin(), it);
}

int main()
{
    int a = 3, b = 1, c = 9;
    std::set<int*> set;

    std::cout << insert_get_index(set, &a) << "\n";
    std::cout << insert_get_index(set, &b) << "\n";
    std::cout << insert_get_index(set, &c) << "\n";
    std::cout << insert_get_index(set, &a) << "\n";
    std::cout << insert_get_index(set, &b) << "\n";
    std::cout << insert_get_index(set, &c) << "\n";

    return 0;
}
0
1
2
0
1
2

在 Visual Studio 2012 中运行代码会产生如下所示的结果。

0
0
2
1
0
2

现在,为什么我认为std::set 的行为与上面描述的一样?因为 cplusplus.com 声明

集合是按照特定顺序存储唯一元素的容器。

此外,还有std::unordered_set

  1. 我是不是对文档的理解有误,而 std::setvalue ordered
  2. 那么std::unordered_set 是什么意思?
  3. 是否有其他标准库容器可以满足我的要求?

【问题讨论】:

  • “是否有其他标准库容器可以满足我的要求?” - 你有什么要求?
  • @MikeSeymour 如上所述,我希望std::set 保持插入值的顺序,但只插入一次。这是我的要求。
  • std::set 是一个有序的关联容器,通常用红黑树实现。
  • @T.C.我以前也染过这个。但它没有指定什么“顺序”(编辑:或者我错过了它,在这种情况下我很抱歉)。
  • 使用您在创建集合时提供的比较器进行排序。默认为std::less&lt;T&gt;

标签: c++ c++11 stl containers stdset


【解决方案1】:

我是否对文档理解有误,而 std::set 是按值排序的?

确实是按值排序的。除非您提供自己的比较器,否则它们是通过使用std::less 比较它们来排序的。对于大多数类型,这使用&lt;。对于指针(通常不能以明确的方式与&lt; 进行比较),它定义了一个未指定但一致的顺序。 (在具有线性地址空间的常见平台上,这可能只是比较地址值;但您不能依赖它)。

因此,在这种情况下,存储指向局部变量的指针取决于编译器选择在哪里为每个变量分配存储空间,这可能因编译器而异。

那么std::unordered_set 是什么?

当您不关心顺序时,这可以提供更好的性能。它使用哈希表提供恒定时间查找,而set 使用搜索树(或类似的东西)提供对数时间查找。

是否有其他标准库容器可以满足我的要求?

不,没有容器既可以保持插入顺序,又可以提供基于值的快速查找。根据您的具体要求,您可以使用vector 来维护订单,并使用std::find 进行线性时间查找;或者您可以使用两个容器,一个用于维护顺序,一个用于提供快速查找,并通过仔细的逻辑使它们保持一致。

【讨论】:

  • ... 或使用 Boost.MultiIndex 为您处理一致性问题。
  • 感谢@MikeSeymour,为您提供这个彻底且易于理解的答案。我现在使用std::vector
猜你喜欢
  • 2015-10-11
  • 2012-04-25
  • 2015-10-27
  • 2018-03-12
  • 2023-04-09
  • 2021-05-30
  • 2014-08-10
  • 1970-01-01
  • 2014-03-15
相关资源
最近更新 更多