[C++ STL] list 详解

标题:[C++ STL] vector 详解

@水墨不写bug



正文开始:

一、背景

C语言阶段,我们如果想要使用链表,需要自己手动实现一个链表。这是非常低效的做法,C++中的STL中提供了链表" list ",我们在包含头文件 <list> 后就可以直接使用。

二、容器简介

list是序列容器,允许在序列内的任何位置进行常量时间的插入和操作,以及两个方向的迭代。

list容器被实现为双链表;双链表可以将它们包含的每个元素存储在不同且不相关的存储位置。排序是通过与前面元素的链接和后面元素的链接的每个元素的关联在内部保持的。

它们与forward_list非常相似:主要区别在于forward_list对象是单链表,因此它只能向前迭代,但是更高效。

与其他基本标准序列容器(array、vector和deque)相比,在已经得到迭代器的情况下,list在容器内的任何位置插入、提取和移动元素方面通常表现更好。因此 list 在大量使用这些操作的算法(如排序算法)中也表现更好。

与其他序列容器相比,list和forward_list的主要缺点是它们无法通过位置直接访问元素;

三、容器接口

(1)默认成员函数

i,构造函数

| default (1) | explicit list (const allocator_type& alloc = allocator_type()); 默认构造,创建一个没有元素的空链表。 cpp list<int> l1; cout << l1.size() << endl; //输出0,链表内默认没有任何元素 |
| fill (2) | explicit list (size_type n); list (size_type n, const value_type& val, const allocator_type& alloc = allocator_type()); 创建一个链表,有n个元素,并将这n个元素初始化为设定值val(如果没有设置,默认初始化为0)。 cpp list<int> l1(5,1); for (const auto e : l1) cout << e << " "; cout << endl; |

range (3) template <class InputIterator> list (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()); 范围初始化,根据迭代器(也可以是其他类型迭代器)区间内的元素的值拷贝来初始化list: cpp vector<int> v1={1,2,3,4,5}; list<int> l1(v1.begin(), v1.end()); for (const auto& e : l1) cout << e << " "; cout << endl;

ii,析构函数

复制代码
~list();

自动销毁实例化的链表,由编译器自动调用。

iii,拷贝构造

copy list (const list& x); list (const list& x, const allocator_type& alloc); 在创建新对象时用已经存在的对象对它初始化: cpp list<int> l1 = { 5,6,8,9 }; list<int> l2(l1); list<int> l3 = l1; for (const auto& e : l2) cout << e << " "; cout << endl; for (const auto& e : l3) cout << e << " "; cout << endl;

iv,赋值重载

copy (1) list& operator= (const list& x); 实现两个list对象的赋值操作: cpp list<int> l1 = { 5,6,8,9 }; list<int> l2; l2 = l1; for (const auto& e : l2) cout << e << " "; cout << endl;

(2)迭代器接口

i,begin()

复制代码
iterator begin() noexcept;
const_iterator begin() const noexcept;

返回一个指向列表容器中第一个元素的迭代器。普通对象调用普通函数,const对象调用const函数。

注意,list::front返回对第一个元素的引用 ,此函数返回指向该元素的双向迭代器。如果容器为空,则返回的迭代器值不能被解引用。

ii,end()

复制代码
 iterator end() noexcept;
const_iterator end() const noexcept;

返回一个迭代器,该迭代器指向列表容器中经过末端的元素。

由于返回的迭代器指向容器中最后一个元素的下一个位置(头节点)。它不含有任何有效数据,因此不能被解引用。

由于标准库函数使用的范围不包括其end迭代器所指向的元素,因此该函数通常与list::begin结合使用,以指定包含容器中所有元素的范围。

如果容器为空,该函数返回与list::begin相同的结果。

iii,rbegin()

复制代码
   reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;

返回指向最后一个元素的反向迭代器。

反向迭代器反向迭代 : 自增它们将移动到容器的起始方向。

rbegin指向成员end所指向的元素的前一个。注意,成员函数 list::back 返回最后一个元素的引用,而此函数返回指向最后一个元素的反向双向迭代器。

iv,rend()

复制代码
   reverse_iterator rend() nothrow;
const_reverse_iterator rend() const nothrow;

返回一个反向迭代器。

该迭代器指向列表容器中第一个元素之前的理论元素(该元素被认为是其反向结束),list::rbegin和list::rend之间的范围包含容器的所有元素(以相反的顺序)。

v,cbegin()

复制代码
const_iterator cbegin() const noexcept;

begin的const版本,begin已经重载了一个const版本,起始即使不使用这个函数,也不会影响const迭代器的正常使用。

vi,cend()

end的const版本,end已经重载了一个const版本,起始即使不使用这个函数,也不会影响const迭代器的正常使用。

vii,crbegin()

rbegin的const版本, rbegin已经重载了一个const版本,起始即使不使用这个函数,也不会影响const迭代器的正常使用。

viii,crend()

rend的const版本,rend已经重载了一个const版本,起始即使不使用这个函数,也不会影响const迭代器的正常使用。

(3)容量接口

i,empty()

判断容器是否为空,为空返回真,否则返回假。

ii,size()

复制代码
size_type size() const noexcept;

返回list内元素的数量。

iii,max_size()

复制代码
size_type max_size() const noexcept;

返回理论上list可存储的最大数量,实际上不具有参考意义。

(4)元素获取

i,front()

复制代码
      reference front();
const_reference front() const;

返回list容器头一个元素的引用。

成员函数 list::begin返回指向同一元素的迭代器,而此函数返回直接引用。在空容器上调用此函数会导致未定义行为。

ii,back()

复制代码
 reference back();
const_reference back() const;

返回list容器最后一个元素的引用。

back是返回容器的最后一个元素的引用,而end是返回最后一个元素下一个位置(头节点)的迭代器。

在空容器上调用此函数会导致未定义行为。

(5)修改

i,push_front()

复制代码
void push_front (const value_type& val);

在列表的开头插入一个新元素,就在它当前的第一个元素之前。val的内容被复制(或移动)到插入的元素中。这高效的将容器大小增加了1。

ii,pop_front()

复制代码
void pop_front();

删除列表容器中的第一个元素,高效地将其大小减小1。这将破坏被删除的元素。

iii,push_back()

复制代码
void push_back (const value_type& val);

在列表容器的最后一个当前元素之后,在其末尾添加一个新元素。val的内容被复制(或移动)到新元素中。这有效地将容器大小增加了1。

iv ,pop_back()

复制代码
void pop_back();

删除列表容器中的最后一个元素,有效地将容器大小减少一个。这将破坏被删除的元素。

v,insert()

| single element (1) | iterator insert (const_iterator position, const value_type& val); 在迭代器position位置插入一个元素val,val如果传入int,则会通过构造函数进行隐式类型转换。(position是下标的值) cpp ostream& operator<<(ostream& out, list<int> l1) { for (const auto& e : l1) cout << e<<" "; cout << endl; return out; } void test1() { list<int> l1 = { 1,2,3,4 }; list<int>::iterator it = l1.begin(); l1.insert(it, 0); cout << l1; } |
| fill (2) | iterator insert (const_iterator position, size_type n, const value_type& val); 在迭代器position位置插入n个val,如果传入int,则会通过构造函数进行隐式类型转换: cpp ostream& operator<<(ostream& out, list<int> l1) { for (const auto& e : l1) cout << e<<" "; cout << endl; return out; } void test1() { list<int> l1 = { 1,2,3,4 }; list<int>::iterator it = l1.begin(); l1.insert(it, 6,0); cout << l1; } |

range (3) template <class InputIterator> iterator insert (const_iterator position, InputIterator first, InputIterator last); 通过另外一个容器的迭代器区间来初始化。

vi,erase()

复制代码
iterator erase (const_iterator position);
iterator erase (const_iterator first, const_iterator last);

可以删除position位置的一个元素;

也可以删除迭代器first和last(左闭右开)区间内的元素。

vii,swap()

交换两个链表的内容:

用x的内容交换容器的内容,x是另一个相同类型的list。大小可能不同。在调用this成员函数之后,this容器中的元素是调用之前在x中的元素,而x的元素是在this容器中的元素。

所有迭代器、引用和指针对于交换后的对象仍然有效。(注意,存在一个具有相同名称的非成员函数,swap,用行为类似于该成员函数的优化重载该算法。)

viii,resize()

复制代码
void resize (size_type n);
void resize (size_type n, const value_type& val);

调整容器的大小,使其包含n个元素。

如果n小于当前容器的大小,则内容将被减少到前n个元素,并删除超出的元素(并销毁它们)。

如果n大于当前容器的大小,则通过在末尾插入所需的元素来扩展内容,以达到n的大小。如果指定了val,则将新元素初始化为val的副本,否则将其进行值初始化。

(注意,这个函数通过插入或删除元素来改变容器的实际内容)

ix,clear()

复制代码
void clear() noexcept;

从列表容器中删除所有元素(这些元素已被销毁),并将容器的大小保留为0。

(6)常见算法接口

i,splice()

entire list (1) void splice (const_iterator position, list& x);
single element (2) void splice (const_iterator position, list& x, const_iterator i);
element range (3) void splice (const_iterator position, list& x, const_iterator first, const_iterator last);

ii,remove()

复制代码
void remove (const value_type& val);

删除具有特定值的元素;

从容器中移除与val比较结果相等的所有元素。调用这些对象的析构函数,并按移除的元素数量减少容器大小。

iii,remove_if()

复制代码
template <class Predicate>
  void remove_if (Predicate pred);

去除满足条件的元素;

从容器中移除Predicate pred返回true的所有元素。这将调用这些对象的析构函数,并根据删除的元素数量减少容器大小。

iv,merge()

(1) void merge (list& x); 通过将列表中各自有序位置的所有元素转移到容器中(两个容器都必须已经有序),将x合并到列表中。

v,sort()

(1) void sort(); 链表排序; 对列表中的元素进行排序,改变它们在容器中的位置。

vi,reverse()

复制代码
void reverse() noexcept;

链表逆置;

目录

一、背景

二、容器简介

三、容器接口

(1)默认成员函数

i,构造函数

ii,析构函数

iii,拷贝构造

iv,赋值重载

(2)迭代器接口

i,begin()

ii,end()

iii,rbegin()

iv,rend()

v,cbegin()

vi,cend()

vii,crbegin()

viii,crend()

(3)容量接口

i,empty()

ii,size()

iii,max_size()

(4)元素获取

i,front()

ii,back()

(5)修改

i,push_front()

ii,pop_front()

iii,push_back()

[iv ,pop_back()](#iv ,pop_back())

v,insert()

vi,erase()

vii,swap()

viii,resize()

ix,clear()

(6)常见算法接口

i,splice()

ii,remove()

iii,remove_if()

iv,merge()

v,sort()

vi,reverse()



完~

未经作者同意禁止转载

相关推荐
XiaoLeisj2 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
励志成为嵌入式工程师3 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉3 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer3 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq3 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
wheeldown4 小时前
【数据结构】选择排序
数据结构·算法·排序算法
记录成长java5 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
前端青山5 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
hikktn5 小时前
如何在 Rust 中实现内存安全:与 C/C++ 的对比分析
c语言·安全·rust
青花瓷5 小时前
C++__XCode工程中Debug版本库向Release版本库的切换
c++·xcode