我首先来说明一个简单的用例示例:
考虑社会安全ID数据库的问题,其中C ++代码被建模为std::unordered_map
,其中密钥是一个人的社会安全ID,其值为std::string
用该人的全名(例如std::unordered_map<int, std::string> DB;
)。
还要考虑,根据个人ID(即std::unordered_map
的密钥)按照升序排序打印此数据库的请求。< / p>
天真地,人们会考虑使用std::sort
来根据请求的标准对std::unordered_map
进行排序,然后将其打印出来,如下面的示例代码所示:
std::sort(DB.begin(), DB.end());
for(auto p : DB) std::cout << "ID(" << p.first
<< ") - "
<< p.second
<< std::endl;
std::sort
或std::unordered_map
的{{1}}会引发编译错误。std::unordered_set
排序STL&#39的无序容器?std::sort
或std::unordered_map
进行排序?答案 0 :(得分:6)
unordered
containers存储内部散列数据,因此在生成散列后无法对其进行排序。
为了对数据进行排序,您可以使用其他非散列容器(例如map或set),并将它们与无序版本一起使用(这样您就可以使用正常的数据对数据进行排序,将无序数据与有快速的每项访问权限)或者你可以做类似
的事情std::map<int, int> ordered(unordered.begin(), unordered.end());
for(auto it = ordered.begin(); it != ordered.end(); ++it)
std::cout << it->second;
我建议不要经常这样做(无序容器有慢速顺序访问)
答案 1 :(得分:5)
排序仅对 sequence 容器有意义, sequence 容器是容器,其元素由它们添加到容器的顺序决定。标准库中的动态序列容器是vector,deque,list和forward_list。
另一方面,地图和集合是关联容器,其中元素由值标识。因此,要求“排序”是没有意义的,因为容器元件没有以任何顺序排列。 (确实,有序地图可以按照键上的比较顺序进行迭代,但是从容器中出现 ;用户不提供它。)
答案 2 :(得分:2)
1.为什么STL的无序容器无法按
std::sort
排序?
因为无序容器已“已排序”,但不是直接由其键,而是(通常)hash_function
(key) %
bucket_count
{{1} }(也可以bucket
()
进行访问)。这种“排序”顺序并不美观 - 它是哈希表能够快速找到元素的完整基础。如果允许(key)
通过键重新排序元素,那么容器将不再能够用作哈希表:无法可靠地找到或删除元素,插入可能会在容器中放置重复项等。
2.是否有合法有效的方式对
std::sort
或std::unordered_map
进行排序?
在一般情况下,只有首先将元素复制到可排序或排序的容器,例如std::unordered_set
或std::vector
(前者通常会更快,但如果您真的关心,则进行基准测试):
std::set
对于std::unordered_set<T> my_set = ...;
std::vector<T> my_vec{my_set.begin(), my_set.end(), my_set.size()};
std::sort(my_vec.begin(), my_vec.end());
,我建议只将std::unordered_map<int, std::string> DB;
个密钥复制到int
进行排序,然后在迭代过程中查找vector
中的每个密钥:这将避免大量unordered_map
复制。
(有时可以通过按键排序来编排无序容器(例如,散列函数返回密钥,容器预先设定为最大桶索引&gt; =最大密钥值),但任何考虑此类滥用的人最好使用{{ 1}}。)