从零开始的C++生活——第七讲——01 从这一讲开始我要引入list了在CSTL中list的实现形式是双向带头循环链表可以说是非常方便了这一篇我来讲一下list的使用。其实有了string和vector的学习基础list的使用学起来还是非常容易的首先list是一个模板类和string以及vector最大的区别是存储空间不连续并且没有reserve这一概念当存储空间不连续的时候迭代器使用就不能同往日而语。对于list的迭代器它并不支持-运算因为内存空间不连续所以你加减其实是没有意义的但是它支持--虽然从语义理解这也是没有意义的但显然是通过运算符重载使得自增自减达到我们想要的效果。对于list这种迭代器叫做双向迭代器对应的还有单项迭代器单向迭代器只能比如单向链表之前我们学的string和vector的迭代器是随机迭代器---都支持。依旧先讲构造函数和vector很像构造函数依旧是有4种分别是默认构造、n值构造、迭代器构造、拷贝构造。#define _CRT_SECURE_NO_WARNINGS 1 #include iostream #include list using namespace std; void test_init() { listint lt; listint lt1(5, 8); listint lt2(lt1.begin(), lt1.end()); listint lt3 lt2; } int main() { test_init(); return 0; }接下来是迭代器对于list迭代器的使用其实注意的点只有上面提到的不能-的问题其他的库已经帮我们实现好了但是简单剧透一下后续模拟实现的时候是很麻烦的。这是一组常规的方法由于list不涉及capacity的概念所以这里也只介绍前两个顾名思义empty是判断list是否为空size则是返回链表中元素个数当链表为空时链表中应该只有一个头节点也就是哨兵位。insert实现了三种方式分别是在指定位置前插入在指定位置前插入n个元素在指定位置前插入迭代器指向的区间void test_insert() { listint lt; listint lt1(5, 8); listint lt2(lt1.begin(), lt1.end()); listint lt3 lt2; lt.insert(lt.begin(), 1); lt3.insert(lt3.begin(), 5, 9); listint::iterator it3_s lt3.begin(); listint::iterator it3_e lt3.end(); for (int i 0; i 3; i) { it3_e--; it3_s; } listint lt4(5, 10); lt4.insert(lt4.begin(), it3_s, it3_e); }这最后一组虽然用的不多但有一些还是蛮新的简单讲一讲。首先为啥algorithm这个库里有sortlist自己还要实现一个呢因为前边说过list的迭代器是双向迭代器不支持-而sort底层是快排不论是挖坑法还是前后指针法还是霍尔都是需要在两边区间找大找小的少不了-所以list自己实现了一个。然后remove其实就是删除和erase不同的是remove是删除值erase则是删除对应位置。splice是转移的意思顾名思义它可以把一个链表的部分转移给某一个链表。merge是合并的意思就是将两个链表合并,要求是两个链表必须有序。void test_other() { listint lt; lt.push_back(1); lt.push_back(35); lt.push_back(12); lt.push_back(89); lt.push_back(13); lt.push_back(1); lt.push_back(9); listint lt2; lt2.push_back(13); lt2.push_back(9); lt2.push_back(3); lt2.push_back(77); lt2.push_back(66); lt2.push_back(11); lt2.push_back(8); //排序 lt.sort(); lt.splice(lt.begin(), lt2); listint lt1(5, 8); lt.sort(); lt.merge(lt1); }关于list的使用就讲到这里了后续将讲解模拟实现