【STL详解 —— list的介绍及使用】

STL详解 ------ list的介绍及使用

list的介绍

  1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
  2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向
    其前一个元素和后一个元素。
  3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高
    效。
  4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率
    更好。
  5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list
    的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间
    开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这
    可能是一个重要的因素)

list的介绍使用

list的构造

  1. 默认构造函数:创建一个空的list容器。
cpp 复制代码
	list<int> v;
  1. 填充构造函数:创建一个具有特定大小的list,可以指定元素的初始值。
cpp 复制代码
	list(size_type n,const value_type& val = value_type())
  1. 拷贝构造函数: 通过复制另一个list来创建一个新的list。
cpp 复制代码
	list (const list& x)
  1. 范围构造函数:通过复制另一个容器或数组的元素范围来创建list。
cpp 复制代码
	list (Inputlterator first, Inputlterator last)
	//用[first,last)区间中的元素构造list

示例:

cpp 复制代码
	list<int> l1;                         // 构造空的l1
    list<int> l2(4, 100);                 // l2中放4个值为100的元素
    list<int> l3(l2.begin(), l2.end());  // 用l2的[begin(), end())左闭右开的区间构造l3
    list<int> l4(l3);                    // 用l3拷贝构造l4


	 // 以数组为迭代器区间构造l5
    int array[] = { 16,2,77,29 };
    list<int> l5(array, array + sizeof(array) / sizeof(int));

    // 列表格式初始化C++11
    list<int> l6{ 1,2,3,4,5 };

list iterator的使用

此处,大家可暂时将迭代器理解成一个指针,该指针指向list中的某个节点。

  1. begin()
cpp 复制代码
iterator begin();const_iterator begin() const;
  1. end()
cpp 复制代码
iterator end();const_iterator end() const;
  1. rbegin()
cpp 复制代码
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
  1. rend()
cpp 复制代码
reverse_iterator rend();
const_reverse_iterator rend() const;

示例

cpp 复制代码
	// 用迭代器方式打印l1中的元素
    list<int>::iterator it = l1.begin();
    while (it != l1.end())
    {
        cout << *it << " ";
        ++it;
    }       
    cout << endl;

    // C++11范围for的方式遍历
    for (auto& e : l1)
        cout << e << " ";

    cout << endl;

list capacity

  1. empty()
    检测list是否为空,是返回true,否则返回false
cpp 复制代码
bool empty() const;
  1. size()
    返回list中有效节点的个数
cpp 复制代码
size_type size() const;

示例:

cpp 复制代码
list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	lt.push_back(5);

	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;

	cout << "lt.size = " << lt.size() << endl;
	

list element access

  1. front()
    返回list的第一个节点中值的引用
cpp 复制代码
T& front();
  1. back()
    返回list的最后一个节点中值的引l用
cpp 复制代码
const T& front() const;

示例:

cpp 复制代码
list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	lt.push_back(5);

	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;

	lt.front()++;	//给lt的第一个元素+1
	lt.back()++;	//给lt的最后一个元素+1

	for (auto& e : lt)
	{
		cout << e << " ";
	}
	cout << endl;

	cout << "lt.size = " << lt.size() << endl;

list modifiers

  1. push_front()
    在list首元素前插入值为val的元素
cpp 复制代码
	void push_front (const value_type& val); 
  1. pop front()
    删除list中第一个元素
cpp 复制代码
void pop_front();
  1. push back()
    在list尾部插入值为val的元素
cpp 复制代码
void push_back (const value_type& val);
  1. pop back()
    删除list中最后一个元素
cpp 复制代码
void pop_back();
  1. insert()
    在listposition位置中插入值为val的元素
cpp 复制代码
single element (1):	
	iterator insert (iterator position, const value_type& val);

fill (2)	:
    void insert (iterator position, size_type n, const value_type& val);
    
range (3)	:
	template <class InputIterator>    
	void insert (iterator position, InputIterator first, InputIterator last);
  1. erase()
    删除listposition位置的元素
cpp 复制代码
iterator erase (iterator position);iterator erase (iterator first, iterator last);
  1. swap()
    交换两个list中的元素
cpp 复制代码
void swap (list& x);
  1. clear()
    清空list中的有效元素

示例

cpp 复制代码
void clear();
cpp 复制代码
#include <iostream>
#include <list>

using namespace std;

int main() {
    // 创建一个空的 list
    list<int> mylist;

    // push_front 在 list 首元素前插入值为 val 的元素
    mylist.push_front(10);
    mylist.push_front(20);
    mylist.push_front(30);

    // 输出 list 中的元素
    cout << "List after push_front:";
    for (int& x : mylist) {
        cout << " " << x;
    }
    cout << endl;

    // pop_front 删除 list 中的第一个元素
    mylist.pop_front();

    // 输出 list 中的元素
    cout << "List after pop_front:";
    for (int& x : mylist) {
        cout << " " << x;
    }
    cout << endl;

    // push_back 在 list 尾部插入值为 val 的元素
    mylist.push_back(40);
    mylist.push_back(50);

    // 输出 list 中的元素
    cout << "List after push_back:";
    for (int& x : mylist) {
        cout << " " << x;
    }
    cout << endl;

    // pop_back 删除 list 中的最后一个元素
    mylist.pop_back();

    // 输出 list 中的元素
    cout << "List after pop_back:";
    for (int& x : mylist) {
        cout << " " << x;
    }
    cout << endl;

    // insert 在 list 中的 position 位置插入值为 val 的元素
    list<int>::iterator it = mylist.begin();
    advance(it, 1); // 将迭代器移动到第二个位置
    mylist.insert(it, 35);

    // 输出 list 中的元素
    cout << "List after insert:";
    for (int& x : mylist) {
        cout << " " << x;
    }
    cout << endl;

    // erase 删除 list 中的 position 位置的元素
    it = mylist.begin();
    advance(it, 2); // 将迭代器移动到第三个位置
    mylist.erase(it);

    // 输出 list 中的元素
    cout << "List after erase:";
    for (int& x : mylist) {
        cout << " " << x;
    }
    cout << endl;

    // 创建另一个 list
    list<int> another_list = { 100, 200, 300 };

    // swap 交换两个 list 中的元素
    mylist.swap(another_list);

    // 输出交换后的 mylist
    cout << "mylist after swap:";
    for (int& x : mylist) {
        cout << " " << x;
    }
    cout << endl;

    // 输出交换后的 another_list
    cout << "another_list after swap:";
    for (int& x : another_list) {
        cout << " " << x;
    }
    cout << endl;

    // clear 清空 list 中的有效元素
    mylist.clear();

    // 输出清空后的 mylist
    cout << "mylist after clear:";
    for (int& x : mylist) {
        cout << " " << x;
    }
    cout << endl;

    return 0;
}

list的迭代器失效

前面说过,此处大家可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节

点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代

器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。

cpp 复制代码
void TestListIterator1()
 {
    int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    list<int> l(array, array+sizeof(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 };
    list<int> l(array, array + sizeof(array) / sizeof(array[0]));
    auto it = l.begin();
    while (it != l.end())
    {
        l.erase(it++);
    }
}
相关推荐
远望清一色9 分钟前
基于MATLAB身份证号码识别
开发语言·图像处理·算法·matlab
NMBG2217 分钟前
[JAVAEE] 面试题(四) - 多线程下使用ArrayList涉及到的线程安全问题及解决
java·开发语言·面试·java-ee·intellij-idea
Py小趴22 分钟前
Python自学之Colormaps指南
开发语言·python·数据可视化
晒足以百八十28 分钟前
基于Python 和 pyecharts 制作招聘数据可视化分析大屏
开发语言·python·信息可视化
敲代码不忘补水1 小时前
生成式GPT商品推荐:精准满足用户需求
开发语言·python·gpt·产品运营·产品经理
清风fu杨柳1 小时前
centos7 arm版本编译qt5.6.3详细说明
开发语言·arm开发·qt
醉颜凉1 小时前
【NOIP提高组】潜伏者
java·c语言·开发语言·c++·算法
_小柏_1 小时前
C/C++基础知识复习(20)
开发语言
hunandede1 小时前
FFmpeg 4.3 音视频-多路H265监控录放C++开发十三.2:avpacket中包含多个 NALU如何解析头部分析
c++·ffmpeg·音视频
程序员小明z1 小时前
基于Java的药店管理系统
java·开发语言·spring boot·毕业设计·毕设