在上篇博客里,我讲到了三种容器适配器:queue,stack和priority_queue ,下面我就简单讲一下我对vector、list及deque 三种容器的理解。
下面两篇博客详细的讲解到vector和list的实现原理以及使用,有兴趣的点链接查看;
vector的模拟实现
list模拟实现
vector和list对比
比较项 | vector | list |
---|---|---|
底层结构 | 动态顺序表,一段连续的空间 | 带头结点的双向循环链表 |
随机访问 | 支持且访问某个元素的效率为O(1) | 不支持,访问某个元素的效率为O(N) |
插入和删除 | 任意地方的插入和删除效率低,需要挪动数据,时间复杂度为O(N),插入时有可能需要增容。增容:开辟新空间,拷贝元素,释放旧空间。故导致效率更低 | 任意地方的插入和删除效率都较高,不需要搬移数据,时间复杂度为O(1) |
空间利用率 | 底层为连续空间,不容易造成内存碎片,空间利用率高,缓存利用率高 | 底层结点动态开辟,小节点容易造成内存碎片,空间利用率低,缓存利用率低 |
迭代器 | 原生态指针 | 对原生态指针(结点指针)进行封装 |
迭代器失效 | 插入元素和删除元素都会导致迭代器失效。插入时可能由增容引起,删除时当前迭代器需要重新赋值否则失效 | 插入元素迭代器不会失效,删除元素当前迭代器会失效,其他迭代器不受影响 |
访问元素 | 三种遍历方式,包括范围for,迭代器和operator[]的访问 | 两种遍历方式,只有迭代器和范围for |
使用场景 | 需要高效存储,支持随机访问,不关心插入删除效率 | 需要大量插入删除操作,不关心随机访问 |
deque
通过上面的对比,大家也发现了,vector和list的优缺点完全相反,所以我们就希望有一个可以折中的方法,使得我们既能高效访问,又能提高插入和删除的效率。这时就有一个deque 的容器为我们提供了这样的思路,但是它自身的优缺点都不明显,所以人们平时用的很少,大价值需要了解它解决这个问题的思想就好了。
deque的底层是一个vector的框架提高元素的访问效率,但增容是按list的方式进行增容(每次增加一个vector),这时我们就能按list思想进行插入和删除。
string
string 也是一个容器,但它进行深拷贝,不需要迭代器。
访问元素有三种方式,迭代器,范围for,operator[]
insert 在string中指插入到下标pos 的下一个位置
insert 在vector和list 中指插入到iterator的位置