list 的底层结构
首先 list 是可以随意插入和删除的序列式容器,迭代器可以双向迭代,它的底层结构是 双向链表 ,在节点中通过指针指向前一个节点和后一个节点
【补充】list 和 forward_list 不同之处是,forward_list 可以向前迭代,已让他更简单高效
优、缺点
优点:相比于 vector,array,deque 在任意位置进行插入和删除更容易
缺点:不支持任意位置的随机访问
list 迭代器
在使用迭代器的时候特别注意会发送迭代器失效的问题 迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响,这个list 迭代式失效的原因和 vector稍稍不同,因为 vector 在插入元素的时候,可能会释放原来的空间,重新申请一块内存空间,但是对于list 是不存在这样的问题,所以 list 在插入的时候不会导致迭代器失效的问题。
void TestListIterator1(){
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
list<int> l(array, array + sizeof(array) / sizeof(array[0]));
auto it = l.begin();
while (it != l.end()){
// erase()函数执行后,it所指向的节点已被删除,
// 因此it无效,在下一次使用it时,必须先给其赋值
l.erase(it);
//赋值之后迭代器就自动指向了被删除节点的后一位
++it;
}
}
vector 和 list 的区别?
-
底层结构:vector 是一段连续的空间,动态顺序表 ;list 是带头结点的双向循环链表
-
随机访问:vector 是支持随机访问,但是list 在访问某一个节点的时候必须要从前往后或者从后往前遍历
-
插入和删除:vector 插入元素的效率低,0(N)有时候还需要增容开启新空间;但是list 可以在任意位置插入或者删除 时间复杂度 O(1)
-
空间利用率 :vector 底层是连续空间,不容易造成内存碎片,空间利用率高,list 底层节点是动态开辟,空间和缓存利用率都低
-
迭代器:vector 是原生态指针,list 对指针进行了封装…(注释:如果迭代器有返回值的时候,返回的时候下一个节点的指针,以防迭代器失效)
-
迭代器失效:vector 在插入和删除的时候都有可能会失效,list 只在删除的时候有可能会失效
-
使用场景:vector 需要高效存储,支持随机访问,不关心插入和删除的效率时,可选择vector ,但是如果大量的插入和删除时候且不关心随机访问的效率可以选择list
带头节点 与 不带头结点的区别?
- 如果有头结点,链表头指针就指向了头结点,如果没有头结点,那头指针指向了链表第一个节点
- 在 插入和 删除 第一个结点的时候比较方便
- 统一空表和非空表的处理:若使用头结点,头指针始终指向头结点,对于空表和非空表的操作是一致的。若不使用头结点,当表非空时,头指针指向第1个结点的地址,但是对于空表,头指针指向的是NULL,此时空表和非空表的操作是不一致的,有很大的概率导致出错
list的模拟实现
https://blog.csdn.net/sinat_36118270/article/details/62417319
链表的面试题
…更新