C++学习笔记(十六)——list

简介: C++学习笔记(十六)——list

list的介绍


list本质是一个带头的双向循环链表

  • list是一种可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
  • list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立结点当中,在结点中通过指针指向其前一个元素和后一个元素。
  • list与forward_list非常相似,最主要的不同在于forward_list是单链表,只能进行单方向迭代。
  • 与其他容器相比,list通常在任意位置进行插入、删除元素的执行效率更高。
  • list和forward_list最大的缺陷是不支持在任意位置的随机访问,其次,list还需要一些额外的空间,以保存每个结点之间的关联信息(对于存储的类型较小元素来说这可能是一个重要的因素)。

list常见接口的介绍


37aeada2d4cb4c57a3382c4b3e907829.png

list的构造函数


1.无参构造:list()

list<int> lt1;

2.用n个值为val的元素构造:list(size_type n,const value_type& val=value_type())

list<int> lt2(10,2);

3.拷贝构造:list(const list& lt)

list<int> lt3(lt2);

4. 用一段区间的元素构造list:list(Inputlterator first,Inputlterator last)

1. string s("hello world");
2. list<char> lt4(s.begin(),s.end());

实例演示

void PrintList(const list<int>& lt)
{
  list<int>::const_iterator it = lt.begin();
  while (it != lt.end())
  {
    cout << *it << " ";
    ++it;
  }
  cout << endl;
}
void test4()
{
  list<int> lt1;
  list<int> lt2(5, 2);
  list<int> lt3(lt2);
  list<int> lt4(lt2.begin(), lt2.end());
  cout << "lt1:";
  PrintList(lt1);
  cout << "It2:";
  PrintList(lt2);
  cout << "It3:";
  PrintList(lt3);
  cout << "It4:";
  PrintList(lt4);
}

代码运行结果如下:

image.png

list中迭代器


1.begin和end

image.png

通过begin函数可以得到容器中第一个元素的正向迭代器,通过end函数可以得到容器中最后一个元素的后一个位置的正向迭代器。

void test12()
{
  list<int> lt(10, 2);
  list<int>::iterator it = lt.begin();
  while (it != lt.end())
  {
    cout << *it << " ";
    it++;
  }
  cout << endl;
}

运行结果:

image.png

2.rbegin和rend

image.png

通过rbegin函数可以得到容器中最后一个元素的反向迭代器,通过rend函数可以得到容器中第一个元素的前一个位置的反向迭代器。

void test13()
{
  list<int> lt;
  lt.push_back(1);
  lt.push_back(2);
  lt.push_back(3);
  lt.push_back(4);
  list<int>::reverse_iterator it = lt.rbegin();
  while (it != lt.rend())
  {
    cout << *it << " ";
    it++;
  }
  cout << endl;
}

运行结果

image.png

list的迭代器遍历


void TestList2()
{
  list<int>lt;
  lt.push_back(1);
  lt.push_back(2);
  lt.push_back(3);
  lt.push_front(0);
  lt.push_front(-1);
  lt.push_front(-2);
  list<int>::iterator it = lt.begin();
  while (it != lt.end())
  {
    cout << *it << " ";
    ++it;
  }
  cout << endl;
  for (auto e : lt)
  {
    cout << e << " ";
  }
  cout << endl;
  list<int>::reverse_iterator rit = lt.rbegin();
  while (rit != lt.rend())
  {
    cout << *rit << " ";
    ++rit;
  }
  cout << endl;
}

运行结果:

image.png

list的增删查改


1.push_front和pop_front

image.png

push_front函数用于头插一个数据,pop_front函数用于头删一个数据。

void test5()
{
  list<int> lt;
  lt.push_front(1);
  lt.push_front(2);
  lt.push_front(3);
  lt.push_front(4);
  for (auto e : lt)
  {
    cout << e << " ";
  }
  cout << endl;
  lt.pop_front();
  for (auto e : lt)
  {
    cout << e << " ";
  }
  cout << endl;
}

演示:

image.png

2.push_back和pop_back

image.png

push_back函数用于尾插一个数据,pop_back函数用于尾删一个数据。

void test6()
{
  list<int> lt;
  lt.push_back(1);
  lt.push_back(2);
  lt.push_back(3);
  for (auto e : lt)
  {
    cout << e << " ";
  }
  cout << endl;
  lt.pop_back();
  for (auto e : lt)
  {
    cout << e << " ";
  }
  cout << endl;
}

演示

image.png

3.insert

image.png

list当中的insert函数支持三种插入方式:

  • 在指定迭代器位置插入一个数。
  • 在指定迭代器位置插入n个值为val的数。
  • 在指定迭代器位置插入一段迭代器区间(左闭右开)。
void test7()
{
  list<int> lt;
  lt.push_back(1);
  lt.push_back(2);
  lt.push_back(3);
  //1.在指定迭代器位置插入一个数
  list<int>::iterator pos = find(lt.begin(), lt.end(), 2);
  lt.insert(pos, 9);
  for (auto e : lt)
  {
    cout << e << " ";
  }
  cout << endl;
  //2.在指定迭代器位置插入n个值为val的数
  pos = find(lt.begin(), lt.end(), 3);
  lt.insert(pos, 2, 8);
  for (auto e : lt)
  {
    cout << e << " ";
  }
  cout << endl;
}

演示:

image.png

4.erase

image.png

list当中的erase函数支持两种删除方式:

1.删除指定迭代器位置的元素。

2.删除指定迭代器区间的所有元素

void test8()
{
  list<int> lt;
  lt.push_back(1);
  lt.push_back(2);
  lt.push_back(3);
  lt.push_back(4);
  lt.push_back(5);
  //删除指定迭代器位置的元素
  list<int>::iterator pos = find(lt.begin(), lt.end(), 2);
  lt.erase(pos);
  for (auto e : lt)
  {
    cout << e << " ";
  }
  cout << endl;
  //删除指定迭代器区间的所有元素
  pos = find(lt.begin(), lt.end(), 4);
  lt.erase(pos, lt.end());
  for (auto e : lt)
  {
    cout << e << " ";
  }
  cout << endl;
}

演示

image.png

相关文章
|
5天前
|
编译器 C语言 C++
【c++丨STL】list模拟实现(附源码)
本文介绍了如何模拟实现C++中的`list`容器。`list`底层采用双向带头循环链表结构,相较于`vector`和`string`更为复杂。文章首先回顾了`list`的基本结构和常用接口,然后详细讲解了节点、迭代器及容器的实现过程。 最终,通过这些步骤,我们成功模拟实现了`list`容器的功能。文章最后提供了完整的代码实现,并简要总结了实现过程中的关键点。 如果你对双向链表或`list`的底层实现感兴趣,建议先掌握相关基础知识后再阅读本文,以便更好地理解内容。
15 1
|
17天前
|
算法 C语言 C++
【c++丨STL】list的使用
本文介绍了STL容器`list`的使用方法及其主要功能。`list`是一种双向链表结构,适用于频繁的插入和删除操作。文章详细讲解了`list`的构造函数、析构函数、赋值重载、迭代器、容量接口、元素访问接口、增删查改操作以及一些特有的操作接口如`splice`、`remove_if`、`unique`、`merge`、`sort`和`reverse`。通过示例代码,读者可以更好地理解如何使用这些接口。最后,作者总结了`list`的特点和适用场景,并预告了后续关于`list`模拟实现的文章。
33 7
|
26天前
|
存储 编译器 C++
C++ initializer_list&&类型推导
在 C++ 中,`initializer_list` 提供了一种方便的方式来初始化容器和传递参数,而右值引用则是实现高效资源管理和移动语义的关键特性。尽管在实际应用中 `initializer_list&&` 并不常见,但理解其类型推导和使用方式有助于深入掌握现代 C++ 的高级特性。
17 4
|
3月前
|
存储 搜索推荐 C++
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
67 2
|
3月前
|
存储 算法 C++
【C++打怪之路Lv10】-- list
【C++打怪之路Lv10】-- list
24 1
|
3月前
|
存储 C++ 容器
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器1
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
75 5
|
3月前
|
存储 编译器 C++
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
85 2
|
3月前
|
C++
【C++】C++ STL 探索:List使用与背后底层逻辑(三)
【C++】C++ STL 探索:List使用与背后底层逻辑
|
3月前
|
C++
【C++】C++ STL 探索:List使用与背后底层逻辑(二)
【C++】C++ STL 探索:List使用与背后底层逻辑
|
3月前
|
存储 编译器 C++
【C++】C++ STL 探索:List使用与背后底层逻辑(一)
【C++】C++ STL 探索:List使用与背后底层逻辑