C++list容器介绍
Posted Suk-god
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++list容器介绍相关的知识,希望对你有一定的参考价值。
文章目录
1、list介绍
- list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
- list的底层是双向循环链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
- list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能向前迭代,以让其更简单高效。
- 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。
- 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)
2、list的底层结构
list的底层结构是一个带头节点的双向循环链表,它可以在任意位置插入或者删除一个元素。
双向:可以正序遍历也可以逆序遍历
循环:找尾结点的时间复杂度为O(1)
带头节点:
①代码实现简单;
②存放end()迭代器,end是最后一个元素的下一个位置;
3、list接口使用
3.1 构造&&析构
3.1.1 构造
1、
explicit list
(const allocator_type& alloc = allocator_type());默认构造函数,构造出来一个仅有头节点的空链表
2、
explicit list (size_type n, const value_type& val = value_type(),
constallocator_type& alloc = allocator_type());使用n个值为val的元素构造双向链表
对于val来说:如果显式提供,就使用提供的值
未提供:内置类型,默认值为0,自定义类型,该类型必须要有默认构造函数3、
template <class InputIterator>
list (InputIterator first, InputIterator last
,const allocator_type& alloc = allocator_type());用区间[first,last)之间的元素来构造双向链表
4、
list (const list& x)
;拷贝构造函数
demo:
3.1.2 析构
~list()
;用来释放资源,在对象使用完毕后会自动调用
3.1.3 赋值运算符重载
list& operator= (const list& x)
;将一个双向链表赋值(拷贝)给另一个双向链表
demo:
3.2 迭代器
begin && end
iterator begin();
| const_iterator begin() const;
iterator end();
| const_iterator end() const;begin:返回链表的第一个元素的位置
end:返回链表的最后一个元素的下一个位置(这里就是头节点的位置)rbegin && rend
reverse_iterator rbegin();
| const_reverse_iterator rbegin() const;
reverse_iterator rend();
| const_reverse_iterator rend() const;rbegin:返回end的位置
rend:返回begin的位置注意 :这两组接口,每个都提供const和非const接口,原因是const对象无法调用非const成员函数,因此需要提供const接口供const对象使用。
demo:
void TestIterators1()
int array[] = 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 ;
list<int> l1(array, array + sizeof(array) / sizeof(array[0]));
const list<int>l2(array, array + sizeof(array) / sizeof(array[0]));
//测试begin&&end
cout << "Before:" << endl;
for (auto iter = l1.begin(); iter != l1.end(); ++iter)
cout << *iter << " ";
cout << endl;
auto it1 = l1.begin();
*it1 = 100;
auto it2 = l2.begin();
// *it2 = 100;//错误写法,l2被const修饰,因此只能调用const成员方法,因此也就无法通过迭代器修改元素的值
++it2;
cout << "After:" << endl;
for (auto iter = l1.begin(); iter != l1.end(); ++iter)
cout << *iter << " ";
cout << endl;
//测试rbegin && rend
cout << "rbegin && rend:" << endl;
for (auto iter = l1.rbegin(); iter != l1.rend(); ++iter)
cout << *iter << " ";
cout << endl;
C++11
cbegin && cend
const_iterator cbegin() const noexcept
;
const_iterator cend() const noexcept
;cbegin:返回链表的第一个元素的位置
cend:返回链表最后一个元素的下一个位置,也就是头节点的位置crbegin && crend
const_reverse_iterator crbegin() const noexcept
;
const_reverse_iterator crend() const noexcept
;crbegin:返回cend的位置
crend:返回crbegin的位置注意:这两组接口的返回值指向的元素不可被修改!
demo:
void TestIterators2()
int array[] = 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 ;
list<int> l1(array, array + sizeof(array) / sizeof(array[0]));
const list<int>l2(array, array + sizeof(array) / sizeof(array[0]));
//测试cbegin&&cend
cout << "Before:" << endl;
for (auto iter = l1.cbegin(); iter != l1.cend(); ++iter)
cout << *iter << " ";
cout << endl;
auto it1 = l1.cbegin();
// *it1 = 100;//错误写法,cbegin返回值指向的元素不可被修改
//测试crbegin && crend
cout << "rbegin && rend:" << endl;
for (auto iter = l1.crbegin(); iter != l1.crend(); ++iter)
cout << *iter << " ";
cout << endl;
3.3 容量相关
bool empty() const
;
size_type size() const
;empty:判空,空–true
size–求链表有效元素个数注意:list没有capacity和reserve方法
demo:
3.4 元素访问相关
reference front();
|const_reference front() const;
reference back();
|const_reference back() const;
front:获取链表的第一个元素
back:获取链表的最后一个元素注意:list没有提供 operator[](size_t index)方法,因为list是带头节点的双向循环链表,不支持随机访问
demo
3.5 修改相关
3.5.1 assign
将新内容分配给列表容器,替换其当前内容,并相应地修改其大小。
template <class InputIterator>
void assign (InputIterator first, InputIterator last)
;使用区间[first,last)之间的元素从新构建新的容器
void assign (size_type n, const value_type& val)
;使用n个值为val的元素重新构建新的容器
void resize (size_type n, value_type val = value_type())
;将链表的有效元素调整为n个
记链表原来的有效元素个数为oldsize
n > oldsize,多出来的结点使用val来填充
n < oldsize,将链表的有效元素个数缩小至n
n == oldsize 不做任何操作
demo:
void TestAssign()
int array[] = 1, 2, 4, 5, 5, 6, 56, 78, 65, 90 ;
list<int> l(array, array + sizeof(array) / sizeof(array[0]));
int temp[] = 100, 200, 300 ;
l.assign(temp, temp + sizeof(temp) / sizeof(temp[0]));
l.assign(10, -100);
3.5.2 头插 && 头删
void push_front (const value_type& val)
;头插一个值为val的元素,时间复杂度O(1)\\
void pop_front()
;头删一个节点,O(1)
demo:
3.5.3 尾插 && 尾删
void push_back (const value_type& val)
;尾插一个值为val的元素,O(1)
void pop_back()
;
尾删,O(1)
demo:
3.5.4 任意位置插入
iterator insert (iterator position, const value_type& val)
;在position位置插入元素val
void insert (iterator position, size_type n, const value_type& val)
;在position位置插入n个值为val的元素
template <class InputIterator>
void insert (iterator position, InputIterator first, InputIterator last)
;在position位置插入区间[first,last)的内容
demo:
3.5.5 任意位置删除
iterator erase (iterator position)
;删除position位置的元素
iterator erase (iterator first, iterator last)
;删除区间[first,last)之间的元素
demo:
3.5.6 swap && clear
void swap (list& x)
;交换两个链表
void clear()
;清空链表
demo:
以上就是对list的基本接口介绍及其使用~!下篇我们模拟实现list,敬请期待
!!!
以上是关于C++list容器介绍的主要内容,如果未能解决你的问题,请参考以下文章