list容器是双向链表,使用前,需要添加#include <list>
1.list的初始化
常用的构造函数如下
explicit list (const allocator_type& alloc = allocator_type());//默认构造函数
explicit list (size_type n);//一般构造函数,初始化list为n个默认值
explicit list (size_type n, const value_type& val, const allocator_type& alloc = allocator_type());//一般构造函数,初始化list为n个val
template <class InputIterator>
list (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type());//一般构造函数,参数为迭代器
list (const list& x);//拷贝构造函数
list (initializer_list<value_type> il, const allocator_type& alloc = allocator_type());//一般构造函数,列表初始化时被调用
构造函数中的allocator_type是一个模板类,作用是提供类型化的内存分配以及对象的分配和撤销
前三个构造函数都是explicit,作用是为了防止隐式转化,具体说明见博客https://blog.csdn.net/Master_Cui/article/details/106885137
void makelist()
{
list<int> l1(5,6);
for (list<int>::iterator it =l1.begin();
it!=l1.end();++it) {
cout<<*it<<endl;
}
list<int> l2(++l1.begin(), --l1.end());
for (list<int>::iterator it =l2.begin();
it!=l2.end();++it) {
cout<<*it<<endl;
}
list<int> l3={1,2,3,4};
for (list<int>::iterator it =l3.begin();
it!=l3.end();++it) {
cout<<*it<<endl;
}
}
注意:因为双向链表的数据结构是链式结构,不是线性结构,所以list的迭代器是双向非随机的,所以不能对list进行随机访问(下标访问),所以不能对迭代器执行以下操作
iter+n
iter-n
iter+=n
iter-=n
iter1-iter2
>, <, >=, <=
总之,list的迭代器不是随机迭代器,迭代器的比较,加减都是非法的,而且凡是用到随机迭代器的算法都不能用来处理list
如果想访问list中的元素,只能通过迭代器进行遍历,或是使用back和front函数进行访问
2.list的赋值
除了使用等号之外,和vector与string类似,也可以使用assign操作
template <class InputIterator>
void assign (InputIterator first, InputIterator last);
void assign (size_type n, const value_type& val);
void assign (initializer_list<value_type> il);
使用方式同vector与string
3.list的访问
由于list的数据是链式结构,所以迭代器是双向非随机的,所以list不支持下标访问和at操作,只能通过front和back函数访问以及通过迭代器进行遍历访问
front函数形式
reference front();
const_reference front() const;
back的函数形式
reference back();
const_reference back() const;
示例和vector与string类似,见博客https://blog.csdn.net/Master_Cui/article/details/107427911
使用迭代器遍历list的情况也和string与vector类似,见上面的示例1
4.list的交换
void swap (list& x);
示例和vector与string类似,见博客https://blog.csdn.net/Master_Cui/article/details/107427911
因为list是双向链表,可以双向操作,所以不仅支持push_back,还支持push_front,当然也支持和vector与string类似的insert
void push_back (const value_type& val);
void push_front (const value_type& val);
iterator insert (const_iterator position, const value_type& val);
iterator insert (const_iterator position, size_type n, const value_type& val);
template <class InputIterator>
iterator insert (const_iterator position, InputIterator first, InputIterator last);
iterator insert (const_iterator position, initializer_list<value_type> il);
上述的函数都是添加元素的操作,insert的返回值依然是第一个插入元素的迭代器,和vector与string一样,参数形式也类似
6.list的删除
因为list是双向链表,可以双向操作,所以同时支持pop_back和pop_front,也支持erase
void pop_back();
void pop_front();
iterator erase (const_iterator position);
iterator erase (const_iterator first, const_iterator last);
两个erase函数的返回值依然是被删除元素的下一个元素的迭代器,和vector与string一样,参数形式也类似
删除操作除了上述四个,还有下面两个
void remove (const value_type& val);//删除所有值为val的元素
template <class Predicate>
void remove_if (Predicate pred);//删除所有使pred(ele)为true的元素(删除所有满足条件的元素)
pred可以是一个函数指针或者函数对象或者lambda表达式
示例1
void removetest()
{
list<int> l;
l.assign(5,6);
l.insert(l.begin(), 3,1);
for (list<int>::iterator it = l.begin();
it!=l.end();++it)
{
cout<<*it<<",";
}
cout<<endl;
l.remove(6);//删除所有的6
for (list<int>::iterator it = l.begin();
it!=l.end();++it)
{
cout<<*it<<",";
}
cout<<endl;
}
示例2
bool isodd(int val) {return val%2==0;}
void removetest2()
{
list<int> l={1,2,3,4,5,6,7};
l.remove_if(isodd);//如果是偶数,删除,否则留下
for (list<int>::iterator it = l.begin();
it!=l.end();++it)
{
cout<<*it<<",";
}
cout<<endl;
}
7.list的迭代器失效
list的迭代器失效只有一种情况,那就是在删除erase操作后,没有更新迭代器
void iteratorfailed()
{
list<int> l={1,2,3,4,5,6,7};
list<int>::iterator it=++l.begin();
l.erase(it);
cout<<*it<<endl;
}
解决办法就是通过erase的返回值更新迭代器it
list迭代器失效的情况之所以很少,是因为list的数据结构导致的,因为list是双向链表,是链式结构,所以元素和元素之间只依靠指针来访问,不能通过下标访问,在删除或添加元素的时候,只需要将指针从新指向新的下一个元素即可,所以,list的删除插入操作的时间复杂度是O(1),不需要在内存中重新移动元素,也正因为元素和元素之间彼此独立,所以也没有预分配空间方法capacity,也就不存在重新分配内存的问题,基于以上原因,对list操作几乎不会使迭代器失效
虽然list没有capacity函数,但是常规的size,empty,resize函数都是有的,同vector与string
参考
《C++ Primer》
《C++标准库》
http://www.cplusplus.com/reference/list/list/
欢迎大家评论交流,作者水平有限,如有错误,欢迎指出