我有一堆完整的重复数据,我想消除重复。你知道,例如[1,1,3,5,5,5,7]变为[1,3,5,7]。
看起来我可以使用std :: map或std :: set来处理这个问题。但是我不确定(a)是否只是将所有值插入容器中,或者(b)检查它们是否已经存在于容器中并且仅在它们不存在时插入 - 是否插入非常有效?即使有更好的方法......你能建议一个快速的方法吗?
另一个问题 - 如果我存储在其中的数据不像整数那么简单,而是一个自定义类,std :: map如何管理以正确存储(哈希?)数据以便快速访问通过运营商[]?
答案 0 :(得分:10)
std::map
不使用散列。 std::unordered_map
确实如此,但那是C ++ 11。 std::map
和std::set
都使用您提供的比较器。类模板具有此比较器的默认值,可归结为operator<
比较,但您可以提供自己的比较器。
如果您不需要存储密钥和值(看起来不是这样),您应该使用std::set
,因为这更合适。
标准没有说明map
和set
在引擎盖下使用的数据结构,只有certian行为具有一定的时间复杂性。实际上,我所知道的大多数实现都使用树。
如果您使用operator[]
或insert
,则时间复杂度没有区别,但我会在insert
之前使用operator[]
或search
insert
如果找不到该项,则后跟{{1}}。后者意味着两个单独的搜索将项目插入到集合中。
答案 1 :(得分:7)
任何关联容器上的insert()
执行find()
以查看对象是否存在,然后插入对象。只需将元素插入std::set<T>
即可合理有效地删除重复项。
根据您的设置的大小以及重复项与唯一值的比率,将对象放入std::vector<T>
,std::sort()
然后再使用std::unique()
可能会更快用std::vector<T>::erase()
来摆脱重复。
答案 2 :(得分:2)
你应该做多少次?
如果通常是插入:
//*/
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
答案 3 :(得分:0)
假设std::map
和std::set
的通用实现策略,即平衡二叉搜索树,插入和查找都必须进行树遍历才能找到密钥所在的位置。因此,插入失败后插入的速度大约是插入速度的两倍。
std :: map如何管理正确存储(哈希?)数据以便通过operator []进行快速访问?
通过您指定的比较功能(或std::less
,如果您在自定义类型上重载operator<
,则该功能可用。在任何情况下,std::map
和std::set
都是不是哈希表。
答案 4 :(得分:0)
std::set
和std::map
都是红黑树。并且可能仅使用插入会更快(然后两者都是因为您将查找时间加倍)。
map
和set
使用operator <
。只要您的班级定义了operator <
,就可以将它们用作关键字。