我可以通过两种方式轻松地在C ++ STL中创建一个键,值属性:映射和对的集合。例如,我可能有
map<key_class,value_class>
或
set<pair<key_class,value_class> >
在算法复杂性和编码风格方面,这些用法之间有什么区别?
答案 0 :(得分:43)
它们语义不同。考虑:
#include <set>
#include <map>
#include <utility>
#include <iostream>
using namespace std;
int main() {
pair<int, int> p1(1, 1);
pair<int, int> p2(1, 2);
set< pair<int, int> > s;
s.insert(p1);
s.insert(p2);
map<int, int> m;
m.insert(p1);
m.insert(p2);
cout << "Set size = " << s.size() << endl;
cout << "Map size = " << m.size() << endl;
}
输出:
设置尺寸= 2
地图大小= 1
答案 1 :(得分:31)
设置元素在集合中时无法修改。 set
的{{1}}和iterator
是等效的。因此,使用const_iterator
时,您无法就地修改set<pair<key_class,value_class> >
。您必须从集中删除旧值并添加新值。但是,如果value_class
是指针,则不会阻止您修改它指向的对象。
使用value_class
,您可以就地修改map<key_class,value_class>
,假设您有对地图的非const引用。
答案 2 :(得分:7)
基本区别在于,对于集合,键是对,而对于映射,键是key_class - 这使得通过key_class查找内容,这是您想要对映射执行的操作,对于集合来说很难。 / p>
两者通常使用相同的数据结构(通常是红黑平衡二叉树)实现,因此两者的复杂性应该相同。
答案 3 :(得分:7)
map<key_class,value_class>
将对key_class进行排序,并且不允许重复使用key_class
如果key_class实例相等,set<pair<key_class,value_class> >
将对key_class和value_class进行排序,并且将允许key_class的多个值
答案 4 :(得分:2)
std::map
充当关联数据结构。换句话说,它允许您使用其关联的键查询和修改值。
可以使std::set<pair<K,V> >
像这样工作,但你必须使用密钥和更多代码来编写查询的额外代码来修改值(即删除旧对并使用相同的密钥插入另一对和不同的价值)。您还必须确保使用相同的密钥不超过两个值(您猜对了,代码更多)。
换句话说,你可以尝试用std::set
来像std::map
一样工作,但没有理由。
答案 5 :(得分:1)
要了解算法的复杂性,首先需要了解实现。
std :: map是使用RB-tree实现的,其中hash_map是使用链表的数组实现的。 std :: map为插入/删除/搜索操作提供O(log(n)),hash_map是O(1)是最好的情况,o(n)在最坏的情况下取决于散列冲突。
答案 6 :(得分:1)