旺道营销软件,seo网站建设教程,代理记账公司利润大吗,西地那非一粒能硬几天文档介绍
文档介绍
1.list是可以在常数范围内的任意位置进行插入和删除的序列式容器#xff0c;并且该容器可以前后双向迭代
2.list的底层是带头双向链表循环结构#xff0c;双向链表中每个元素存储在互不相关的独立节点中#xff0c;在节点中通过指针指向其前一个元素和…文档介绍
文档介绍
1.list是可以在常数范围内的任意位置进行插入和删除的序列式容器并且该容器可以前后双向迭代
2.list的底层是带头双向链表循环结构双向链表中每个元素存储在互不相关的独立节点中在节点中通过指针指向其前一个元素和后一个元素
3.list和forward_list非常相似最主要的不同在于forward_list是单链表只能朝前迭代已让其更简单高效
4.与其他的序列式容器相比arrayvectordequelist通常在任意位置进行插入、移除元素的执行效率更好
5.与其他序列式容器相比list和forward_list最大的缺陷是不支持任意位置的随机访问比如要访问list的第6个元素必须从已知的位置比如头部或者尾部迭代到该位置在这段位置上迭代需要线性的时间开销list还需要一些额外的空间以保存每个节点的相关联信息对于存储类型较小元素的大list来说这可能是一个重要的因素
注意事项
1.list没有扩容的方法 2.list不支持[]访问不是连续存储的 3.remove移除元素有则删除没有不报错 4.splice粘接转移元素 5.迭代器的分类 1 单向迭代器 如单链表 2 双向迭代器–如list 3 随机迭代器–-如vector 下面的包含上面迭代器的功能
下图是list的迭代器
6.链表为什么自己实现了sort不像vector一样用算法库的sort。因为算法库的sort用的是快速排序里面的三数取中对于链表不能用且sort的参数也有提示
sort需要传的是随机迭代器而链表的是双向迭代器理论上模板可以传任意参数但内部使用迭代器有要求
7.list的sort效率不太高100万数据和vector差了4倍
使用
构造
构造函数 constructor接口说明list (suze_type n, const value_type val value_type())构造的list中包含n个值为val的元素list ()构造空的listlist (const list x)构造拷贝函数list (InputIterator first, InputIterator last)用(first, last)区间中的元素构造list listint l1; // 构造空的l1listint l2(4, 100); // l2中放4个值为100的元素listint l3(l2.begin(), l2.end()); // 用l2的[begin(), end()左闭右开的区间构造l3listint l4(l3); // 用l3拷贝构造l4// 以数组为迭代器区间构造l5int array[] { 16,2,77,29 };listint l5(array, array sizeof(array) / sizeof(int));// 列表格式初始化C11listint l6{ 1,2,3,4,5 };迭代器
迭代器理解成一个指针,指向list中某个节点
函数声明接口说明begin end返回第一个元素的迭代器 返回最后一个元素下一个位置的迭代器rbegin rend返回第一个元素的reverse_iterator,即end位置,返回最后一个元素下一个位置的reverse_iterator,即begin的位置
begin和end为正向迭代器,对迭代器执行操作,迭代器向后移动 rbegin和rend为反向迭代器,操作,向前移动 // 用迭代器方式打印l5中的元素listint::iterator it l5.begin();while (it ! l5.end()){cout *it ;it;} cout endl;// C11范围for的方式遍历for (auto e : l5)cout e ;cout endl;
}
// list迭代器的使用
// 注意遍历链表只能用迭代器和范围for
void PrintList(const listint l)
{// 注意这里调用的是list的 begin() const返回list的const_iterator对象for (listint::const_iterator it l.begin(); it ! l.end(); it){cout *it ;// *it 10; 编译不通过}cout endl;
}void TestList2()
{int array[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };listint l(array, array sizeof(array) / sizeof(array[0]));// 使用正向迭代器正向list中的元素// listint::iterator it l.begin(); // C98中语法auto it l.begin(); // C11之后推荐写法while (it ! l.end()){cout *it ;it;}cout endl;// 使用反向迭代器逆向打印list中的元素// listint::reverse_iterator rit l.rbegin();auto rit l.rbegin();while (rit ! l.rend()){cout *rit ;rit;}cout endl;
}容量
函数声明接口说明empty检测list是否为空,返回true,否则返回falsesize返回list中有效节点的个数front返回list的第一个节点中值的引用back返回list的最后一个节点中值的引用
修改
函数声明接口说明push_front在list首元素前插入值为val的元素pop_front删除list中第一个元素push_back在list尾部插入值为val的元素pop_back删除list中最后一个元素insert在list position位置中插入值为val的元素erase删除lsit position位置的元素swap交换两个lsit的元素clear清空list的有效元素
// list插入和删除
// push_back/pop_back/push_front/pop_front
void TestList3()
{int array[] { 1, 2, 3 };listint L(array, array sizeof(array) / sizeof(array[0]));// 在list的尾部插入4头部插入0L.push_back(4);L.push_front(0);PrintList(L);// 删除list尾部节点和头部节点L.pop_back();L.pop_front();PrintList(L);
}// insert /erase
void TestList4()
{int array1[] { 1, 2, 3 };listint L(array1, array1 sizeof(array1) / sizeof(array1[0]));// 获取链表中第二个节点auto pos L.begin();cout *pos endl;// 在pos前插入值为4的元素L.insert(pos, 4);PrintList(L);// 在pos前插入5个值为5的元素L.insert(pos, 5, 5);PrintList(L);// 在pos前插入[v.begin(), v.end)区间中的元素vectorint v{ 7, 8, 9 };L.insert(pos, v.begin(), v.end());PrintList(L);// 删除pos位置上的元素L.erase(pos);PrintList(L);// 删除list中[begin, end)区间中的元素即删除list中的所有元素L.erase(L.begin(), L.end());PrintList(L);
}
迭代器失效
前面说过此处大家可将迭代器暂时理解成指针迭代器失效即迭代器所指向的节点无效该节点被删除了因为list的底层结构为带头节点的双向循环链表因此在list中插入时不会导致list的迭代器失效只有删除才会并且失效的只是指向被删除节点的迭代器其他迭代器不会受影响
void TestListIterator1()
{int array[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };listint l(array, arraysizeof(array)/sizeof(array[0]));auto it l.begin();while (it ! l.end()){// erase()函数执行后it所指向的节点已被删除因此it无效在下一次使用it时必须先给
其赋值l.erase(it); it;}
}
// 改正
void TestListIterator()
{int array[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };listint l(array, arraysizeof(array)/sizeof(array[0]));auto it l.begin();while (it ! l.end()){l.erase(it); // it l.erase(it);}
}