https://blog.csdn.net/qq_43313035/article/details/89600276
顺序容器:
vector
deque
list
关联容器:
特点:
增加新元素时,如果超出当前容量,则容量会扩充至两倍。如果两倍还不够,则扩张至足够大的空间。
容量的扩张:
vector 对象本身在栈上,里面的成员指针指向堆。
vector 和基本数据类型一样使用,定义指针一样。
vector 内的元素存放在堆中,由STL库中的程序负责分配和释放,使用方便,但是效率低下。
原生数组的执行效率是vector的10倍左右,因为他内存的分配和释放完全由系统自动完成。
vector效率低下的原因:vector的动态自增,并不是在原空间之后接续新空间,而是在原空间不够使用时,以原空间大小的两倍另外配置一块大空间,然后将原内容拷贝过来,再在新拷贝的原内容之后构造新元素,并释放原空间。
size指的是当前拥有的元素个数,capacity指的是vector当前分配的总个数,所有capacity>=size。
特点:
deque采用一块所谓的map(注意,不是STL的map容器)作为主控。这里所谓map是一小块连续空间,其中每个元素(此处称为一个节点,node)都是指针,指向另一段(较大的)连续线性空间,称为缓冲区。缓冲区才是deque的储存空间主体
为什么list容器可以很方便的随机插入:
list是一个线性双向链表结构,它的数据由若干个节点构成,每一个节点都包括一个信息块(即实际存储的数据)、一个前驱指针和一个后驱指针。它无需分配指定的内存大小且可以任意伸缩,这是因为它存储在非连续的内存空间中,并且由指针将有序的元素链接起来。由于其结构的原因,list 随机检索的性能非常的不好,因为它不像vector 那样直接找到元素的地址,而是要从头一个一个的顺序查找,这样目标元素越靠后,它的检索时间就越长。检索时间与目标元素的位置成正比。虽然随机检索的速度不够快,但是它可以迅速地在任何节点进行插入和删除操作。因为list 的每个节点保存着它在链表中的位置,插入或删除一个元素仅对最多三个元素有所影响,不像vector 会对操作点之后的所有元素的存储地址都有所影响,这一点是vector 不可比拟的。
特点:
特点:
特点:
unordered_map内部实现了一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序是无序的。
特点:
优点: 因为内部实现了哈希表,因此其查找速度非常的快
缺点: 哈希表的建立比较耗费时间
适用处:对于查找问题,unordered_map会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map
hash_map基于hash table(哈希表)。
哈希表最大的优点:
就是把数据的存储和查找消耗的时间大大降低,几乎可以看成是常数时间;而代价仅仅是消耗比较多的内存。然而在当前可利用内存越来越多的情况下,用空间换时间的做法是值得的。另外,编码比较容易也是它的特点之一。
其基本原理是:
使用一个下标范围比较大的数组来存储元素。可以设计一个函数(哈希函数,也叫做散列函数),使得每个元素的关键字都与一个函数值(即数组下标,hash值)相对应,于是用这个数组单元来存储这个元素;也可以简单的理解为,按照关键字为每一个元素“分类”,然后将这个元素存储在相应“类”所对应的地方,称为桶。
但是,不能够保证每个元素的关键字与函数值是一一对应的,因此极有可能出现对于不同的元素,却计算出了相同的函数值,这样就产生了“冲突”,换句话说,就是把不同的元素分在了相同的“类”之中。
总的来说,“直接定址”与“解决冲突”是哈希表的两大特点。
hash_map,首先分配一大片内存,形成许多桶。是利用hash函数,对key进行映射到不同区域(桶)进行保存。其插入过程是:
其取值过程是:
hash_map和map的区别在哪里?
什么时候需要用hash_map,什么时候需要用map?
总体来说,hash_map 查找速度会比map快,而且查找速度基本和数据数据量大小,属于常数级别;而map的查找速度是log(n)级别。并不一定常数就比log(n)小,hash还有hash函数的耗时,明白了吧,如果你考虑效率,特别是在元素达到一定数量级时,考虑考虑hash_map。但若你对内存使用特别严格,希望程序尽可能少消耗内存,那么一定要小心,hash_map可能会让你陷入尴尬,特别是当你的hash_map对象特别多时,你就更无法控制了,而且hash_map的构造速度较慢。
关于Rehash
当键值对的数量>=设定的阀值(capacity * load factor(0.75))时,为保证HashMap的性能,会进行重散列(rehash)。
HashMap中,重散列主要有两步:1、扩充table长度。2、转移table中的entry,从旧table转移到新的table。
table长度以2倍的方式扩充,一直到最大长度2^30。
entry转移的过程是真正意义上的重散列,在此过程中,对原来的每个entry的key重新计算新的散列地址,旧table中相同位置的entry极有可能会被散列到新table中不同的位置,这主要是因为table的length变化的原因。
优先队列不是按照普通对象先进先出原FIFO则进行数据操作,其中的元素有优先级属性,优先级高的元素先出队。
优先队列的底层实现是堆,默认的优先队列是从大到小排序,底层也就是大顶堆。
优先队列的插入删除和大顶堆基本相同,每次插入和删除都需要进行对应的上浮和下沉操作,所有优先队列的入队和出队时间复杂度是logn。
PriorityQueue队列不适合经常出队入队的频繁操作,但是他的优先级特性非常适合一些对顺序有要求的数据处理场合。