最近unordered_map在C++中的讨论使我意识到,我应该使用之前使用unordered_map过的大多数情况map,因为查找的效率(摊销的O(1)与O(log n)).大多数时候我使用的地图我使用int或std::string作为键,因此我对哈希函数的定义没有任何问题.我越是想到它,我就越发现我发现std::map在一个简单类型的情况下我找不到任何理由std::unordered_map- 我看了一下界面,并没有发现任何显着的差异会影响我的代码.
因此,这个问题-有没有使用任何真正的原因std::map在std::unordered map简单类型一样的情况下,int和std::string?
我从一个严格的编程角度问我 - 我知道它没有被完全认为是标准的,并且它可能会带来移植问题.
另外我希望正确的答案之一可能是"它对于较小的数据集更有效",因为开销较小(是真的吗?) - 因此我想将问题限制在密钥数量的情况下是非平凡的(> 1 024).
编辑: 呃,我忘记了显而易见的(感谢GMan!) - 是的,地图是当然有序的 - 我知道,我正在寻找其他原因.
堆和BST有什么区别?
何时使用堆以及何时使用BST?
如果你想以排序的方式获取元素,BST是否优于堆?
遇到了这个很好的问题,这个问题类似但完全不同,因为它讨论了Java,它具有不同的哈希表实现,因为它具有同步访问器/ mutators HashMap和Hashtable之间的差异?
那么set和unordered_set的C++实现有什么不同呢?对于其他C++容器,这个问题可以扩展到map vs unordered_map等等.
这是我的初步评估
set:虽然标准并没有明确要求它实现为树,但时间复杂性约束要求查找/插入操作,这意味着它将始终实现为树.通常作为RB树(如GCC 4.8中所见),它是高度平衡的.由于它们是高度平衡的,因此它们具有可预测的find()时间复杂度
优点:紧凑(与其他DS相比)
Con:访问时间复杂度为O(lg n)
unordered_set:虽然标准并没有明确要求它实现为树,但时间复杂度约束要求查找/插入操作,这意味着它将始终实现为哈希表.
优点:
缺点:
注意:哈希表的O(1)来自假设没有冲突.即使负载系数为.5,每隔一次变量插入也会导致碰撞.可以观察到,散列表的负载因子与访问其中的元素所需的操作数成反比.我们减少了#operations,sparser hash-table.当存储的元素大小与指针相当时,开销非常重要.
编辑:由于大多数人都说问题中包含足够的答案,我正在将问题改为"我是否会错过地图/集合之间的任何区别,以便进行性能分析?"
通常,使用排序std::vector而不是a 更有效std::set.有没有人知道一个库类sorted_vector,它基本上有一个类似的接口std::set,但插入元素到排序的矢量(所以没有重复),使用二元搜索find元素等?
我知道写起来并不难,但最好不要浪费时间并使用现有的实现.
更新:使用排序向量而不是集合的原因是:如果您有数十万个小集合,每个集合只包含10个左右的成员,那么使用排序向量代替更高内存效率.
我想知道如何在C++中实现一个集合.如果我在不使用STL提供的容器的情况下实现自己的set容器,那么最好的方法是什么呢?
我理解STL集基于二叉搜索树的抽象数据结构.那么底层数据结构是什么?数组?
另外,如何insert()为一组工作?set如何检查元素是否已经存在?
我在维基百科上读到,实现集合的另一种方法是使用哈希表.这怎么样?
在这里http://www.cplusplus.com/reference/stl/set/我读到用C++中的std :: set"通常"实现为树(红黑色?)并对其进行排序.
我无法理解,这是否意味着通过规范迭代的顺序总是提升?或者它只是"通常的实现细节",有时,某些库/编译器可能违反此约定?
我可以在C++中创建一个无序的向量集吗?这样的事情
std::unordered_set<std::vector<int>> s1;
Run Code Online (Sandbox Code Playgroud)
因为我知道std lib的"set"类是可能的,但似乎它不适用于无序版本谢谢
更新:这是我正在尝试使用的确切代码
typedef int CustomerId;
typedef std::vector<CustomerId> Route;
typedef std::unordered_set<Route> Plan;
// ... in the main
Route r1 = { 4, 5, 2, 10 };
Route r2 = { 1, 3, 8 , 6 };
Route r3 = { 9, 7 };
Plan p = { r1, r2 };
Run Code Online (Sandbox Code Playgroud)
如果我使用set,它可以,但在尝试使用无序版本时收到编译错误
main.cpp:46:11: error: non-aggregate type 'Route' (aka 'vector<CustomerId>') cannot be initialized with an initializer list
Route r3 = { 9, 7 };
Run Code Online (Sandbox Code Playgroud) 我有一个整数数组,我需要删除重复项,同时保持每个整数第一次出现的顺序.我可以看到这样做,但想象有一种更好的方法可以更好地利用STL算法吗?插入不受我的控制,因此在插入之前我无法检查重复项.
int unsortedRemoveDuplicates(std::vector<int> &numbers) {
std::set<int> uniqueNumbers;
std::vector<int>::iterator allItr = numbers.begin();
std::vector<int>::iterator unique = allItr;
std::vector<int>::iterator endItr = numbers.end();
for (; allItr != endItr; ++allItr) {
const bool isUnique = uniqueNumbers.insert(*allItr).second;
if (isUnique) {
*unique = *allItr;
++unique;
}
}
const int duplicates = endItr - unique;
numbers.erase(unique, endItr);
return duplicates;
}
Run Code Online (Sandbox Code Playgroud)
如何使用STL算法完成?
从cplusplus.com参考,它似乎std::set排序元素.
我需要排序字符串,但我不确定它是否适用于每个平台和编译器.主要是GCC,MinGW,VC.
我想知道为什么会用std::unordered_multiset。我的猜测是它与插入/擦除后迭代器的无效或非无效有关,但也许更深层吗?非常相似的问题在这里:std :: multimap的用例,但更多是关于地图的讨论。
假设我有一个unordered_set<int> S.
我知道我可以通过以下方式迭代:
void iterate(){
for (const auto& elem: S) {
cout<<elem<<endl;
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:如果我打电话iterate()并打印出一定数量的数字,是否可以保证如果我iterate()按照我想要的次数打电话,它会一直打印相同的序列?
假设那个sizeof(void*) == sizeof(size_t)哈希指针只是将其转换为size_t.所以我想知道我的集合是否包含一个元素,它会更快std::set<void*>还是std::unordered_set<void*>?
我知道怎么std::set运作,但我不熟悉std::unordered_set.好吧,我知道无序集使用散列和桶,如果没有交叉(这是我的情况),复杂性是O(1).但我不知道这种复杂程度有多大.
如果容器中的日期相关,我的实际情况使用不到一百¹.但是我的好奇心只涉及几个元素和很多元素的情况.
¹元素的数量很少,甚至std::vector可以表现良好.
c++ ×10
c++11 ×4
set ×4
stl ×4
algorithm ×2
performance ×2
sorting ×2
vector ×2
binary-tree ×1
dictionary ×1
duplicates ×1
hashset ×1
heap ×1
std ×1
stdset ×1
stdvector ×1