C++ std::map 或 std::set - 有效地插入重复项
C++ std::map or std::set - efficiently insert duplicates
我有一堆充满重复的数据,我想消除重复项。你知道,例如 [1, 1, 3, 5, 5, 5, 7] 变成 [1, 3, 5, 7]。
看起来我可以使用 std::map 或 std::set 来处理这个问题。但是,我不确定 (a) 简单地将所有值插入容器中,还是 (b) 检查它们是否已经存在于容器中并且仅在不存在时才插入 - 插入是否非常有效?即使有更好的方法...你能建议一种快速的方法吗?
另一个问题 - 如果我存储在其中的数据不像整数那样微不足道,而是一个自定义类,那么 std::map 如何设法正确存储(哈希?)数据以便通过 operator[] 快速访问?
std::map
不使用哈希。 std::unordered_map
确实如此,但那是C++11。 std::map
和std::set
都使用您提供的比较器。 类模板具有此比较器的默认值,归结为operator<
比较,但您可以提供自己的比较。
如果你不需要同时存储键和值(看起来你不需要),你应该只使用std::set
,因为这更合适。
该标准没有说明map
和set
在引擎盖下使用哪些数据结构,只是说某些操作具有一定的时间复杂性。 实际上,我知道的大多数实现都使用树。
operator[]
或 insert
,则在时间复杂度方面没有区别,但是我会在我做search
之前使用 insert
或 operator[]
,如果没有找到该项目,则使用insert
。 后者意味着进行两次单独的搜索以将项目插入到集合中。
任何关联容器上的insert()
都会执行find()
以查看对象是否存在,然后插入对象。只需将元素插入std::set<T>
中,就可以合理有效地消除重复项。
根据集合的大小以及重复项与唯一值的比率,将对象放入 std::vector<T>
中可能会更快,然后std::sort()
,然后将std::unique()
与std::vector<T>::erase()
一起使用以删除重复项。
你应该做多少次?
如果通常插入:
//*/
std::set<int> store;
/*/
// for hash:
std::unordered_set<int> store;
//*/
int number;
if ( store.insert(number).second )
{
// was not in store
}
如果您填写一次:
std::vector<int> store;
int number;
store.push_back(number);
std::sort(store.begin(),store.end());
store.erase(std::unique(store.begin(),store.end()),store.end() );
// elements are unique
假设std::map
和std::set
的共同实现策略,即平衡的二叉搜索树,插入和查找都必须进行树遍历以找到键应该在的位置。因此,失败的查找后插入的速度大约是插入的两倍。
std::map 如何设法正确存储(哈希?)数据,以便通过 operator[] 快速访问?
通过您指定的比较函数(或std::less
,如果您在自定义类型上重载operator<
,则该函数有效)。在任何情况下,std::map
和std::set
都不是哈希表。
std::set
和std::map
都实现为红黑树。并且可能仅使用插入会更快(然后两者都是因为您将查找时间加倍)。
也map
和set
使用operator <
。只要您的类定义了operator <
它就可以将它们用作键。
- 有效地使用std::unordered_map来插入或增加键的值
- 将重物插入std::map
- 如何有效地在 std::vector 中插入一对?
- 在基于范围的 for 循环期间插入 std::list 的后面
- 为 std::vector 编写自定义插入函数
- std::unordered_map 如果输入大小已知,如何优化批量插入
- C++ - 最坏情况和平均情况插入时间复杂度在 std::unordered_map <int,int>?
- 找不到最新插入到 std::map 中的键
- 在 std::map 中插入数组元素
- 有没有更快的方法可以在 std::vector 中插入元素
- 插入 std::set 作为 std::map 的键
- 通过构造函数插入 std::map
- 将带有模板的自定义类插入到 std::map 中
- 如何将 n 个连续元素插入到元素类型不可复制的 std::vector 中?
- 将唯一指针插入std::映射
- 如果迭代器没有因插入而无效,则使用std::find和C::insert()是线程安全的
- std::为插入和排序设置不同的比较器
- std::映射导致插入时出现C2664错误
- 为什么std ::插入需要复制构造性
- std::插入无序集合(或映射)的迭代器