【问题标题】:How does unordered_set determine the inserting order in c++?unordered_set 如何确定 c++ 中的插入顺序?
【发布时间】:2016-12-26 18:26:35
【问题描述】:

我知道人们在不关心集合中元素的顺序时会使用unordered_set。但是,当我在C++ Shell上运行示例程序时

#include <iostream>
#include <unordered_set>
#include <string>

int main()

{
std::unordered_set<std::string> inputSet;
inputSet.insert("Hello world");
inputSet.insert("Abcdef");
inputSet.insert("This is the test string...");

for(const auto &val : inputSet)
  std::cout << val.c_str() << std::endl;

return 0;}

它给了我

This is the test string...
Abcdef
Hello world

我尝试运行它 3 或 4 次,它仍然给我相同的输出,这意味着 unordered_set 可以确定插入顺序。

谁能解释unordered_set如何确定插入顺序?

对不起,如果之前有人问过,我已经在网上搜索了一段时间,但我找不到这个问题的具体答案。提前致谢。

【问题讨论】:

  • 为什么你还需要知道?在任何情况下,您都不应试图依赖订单。
  • @mclaassen 有时候我们应该有好奇心。

标签: c++ unordered-set


【解决方案1】:

没有特定的顺序...它使用默认的std::hash 来散列字符串。并且无论hash值是什么,都会被转换成容器中合适的桶索引..

可以得到我们所说的hash值:

auto hello = std::hash<std::string>()("Hello world");
auto abcd = std::hash<std::string>()("Abcdef");
auto test = std::hash<std::string>()("This is the test string...");

对于特定的 STL 实现,这会解析为:

Hello maps to: 14420674105493498572
abcd maps to: 10830572898531769673
test maps to: 13068738153895491918

C++Shell观看直播

该值通常通过应用% 运算符转换为适当的桶索引。同样,std::unordered_set 的迭代器并没有强制要求按顺序遍历所有存储桶(碰撞呢?)。因此,您不应该依赖从程序运行之间的迭代器中观察到的任何顺序。


从 C++14 开始,std::hash&lt;&gt; 被明确允许在不同的程序运行之间产生不同的结果。致quote

哈希函数只需要产生相同的结果 在程序的单次执行中输入相同的输入;这允许腌制 防止冲突 DoS 攻击的哈希值。

【讨论】:

  • 当我使用bucket方法并输入一些我没有放入无序集中的东西时,它仍然返回一些bucket,这是为什么?
  • 我也试着找到这三个的桶,结果是一样的,但是他们有不同的哈希??
【解决方案2】:

如此处所述http://en.cppreference.com/w/cpp/container/unordered_set

在内部,元素不是按任何特定顺序排序的,而是 组织成桶。将元素放入哪个桶取决于 完全基于其值的散列。这允许快速访问 单个元素,因为一旦计算了散列,它指的是 元素放入的确切存储桶。

所以它要么使用默认或用户提供的哈希算法来排序到哈希桶中。

【讨论】:

  • 所以你是说没有办法预测输出?
  • @user2185071 我认为输出的“可预测性”取决于:类型(因为类型决定了哈希值,它只是一个数字)和插入顺序(因为对于相同的哈希 -- 不太可能;顺序与插入顺序相同)。
  • 无序集针对插入和检索进行了优化,而不是遍历。如果您优先考虑广告订单,请使用其他容器。
【解决方案3】:

std::unordered_set&lt;T&gt; 中的顺序是无序的。但是,假设使用确定性哈希并且执行相同顺序的插入操作,则程序的不同运行将具有相同顺序的元素。以不同的顺序插入元素和/或使用为不同的运行产生不同值的哈希将产生不同的元素顺序。

【讨论】:

    猜你喜欢
    • 2018-03-12
    • 2012-12-30
    • 2021-01-15
    • 1970-01-01
    • 2021-05-10
    • 2014-08-10
    • 2020-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多