序列容器和关联容器结构上的区别
关联式容器是按照元素的键值存储,使得元素可以快速访问和查找(内存一般不连续);序列式容器是将元素按照线性序列存储,可以按照位置进行访问和修改(内存连续)。
最基本的访问
在序列容器中,g[n]是o(1);而在关联容器中,对于哈希存储的unordered_map和unordered_set,g[n]一般是o(1),
在最坏情况下,当哈希函数产生的哈希值非常糟糕,导致所有的元素都映射到同一个哈希桶中时,
g[n]
的时间复杂度会退化为 O(n)。这是因为在这种情况下,需要遍历整个哈希桶来查找或插入元素;对于红黑树(平衡查找/搜索树)存储的map和set,g[n]是logn(如果不存在就插入)。
std::find和.find
在序列容器中,没有键值概念,都是直接存储元素;在关联容器中,有键值的说法。这决定了std::find算法和.find函数。std::find算法是针对序列容器设计的,参数是.begin(),.end(),和值,注意是值——时间复杂度是o(n),根据迭代器遍历整个容器——返回的是迭代器;.find()是关联容器的成员函数,参数是键,注意是键——时间复杂度是o(1)/o(logn)/等,直接根据关联容器的结构(如哈希表/红黑树/等)查找——返回的是迭代器(例如在unordered_map中,返回的迭代器,是指向pair类型的指针,如果需要接着访问pair里的元素,应使用it->first/it->second,first和second是公共成员而不是函数不用(),it是指针不能用.first)。
std::count和.count
类似于std::find,和.find。std::count是为序列容器设计的,遍历整个容器返回对应值的个数,>0;而.count是关联容器的成员函数,键不允许重复,直接根据数据结构查找(o(1)/o(logn)/等),只会返回0/1。
count和find的使用场景区别
当我们只需要知道容器里是否有这个值/键的时候,使用count即可,当我还需要找到它并对它进行操作的时候,使用find。
std::sort
sort函数只适用于提供随机迭代器的容器(很多时候是快速排序)。关联容器内存不连续,显然不能提供随机迭代器,关联容器的排序( 某些关联容器
在插入元素时就已经按照键的顺序进行了排序(对于
unordered_
系列的容器,是根据哈希值分布的,不是真正的排序)
)选用对应的容器即可,unordered_map-map,unordered_set-set,如果想自己指定排序方法,只需在构造map/set时提供第三个参数即比较函数即可。大部分序列容器提供随机迭代器,可以用std::sort,而像list序列容器的实现是双向链表,为了方便o(1)的插入删除,不提供随机迭代器,它的排序提供了成员函数.sort(底层用归并排序,o(nlogn))。