第九层(7):STL之list(上)

简介: 第九层(7):STL之list(上)

前情回顾


在上一块石碑中,我学到了queue,同时下一块石碑也显露出来…


🚄上章地址:第九章(6):STL之queue


list


概念


list可以将数据链式存储,list也就是链表,链表是由一系列的节点组成,节点是内部有两块区域,一个是存放下一个节点地址的指针域,一个是存放数据的数据域,链表可以对任意位置进行快速的插入和删除,但是因为链表不是一块连续的空间,所以遍历的速度慢于数组,并且占用空间比数组要大,list的本质就是一个双向循环链表,双向循环列表指的就是,第一个节点记录着最后的位置,最后一个节点记录第一个节点的位置

0a2653c851af460fa595bd959398a8f1.png


由于链表的储存方法不是连续空间,所以list的迭代器只支持前移和后移,属于双向迭代器,不能随机访问


优缺点


优点:

采用动态存储分配,不会造成内存的浪费和溢出

list的插入和删除十分方便,只需要修改指针就可以,不需要移动内部的大量数据

list的插入和删除不会造成原有的迭代器失效,而vector不行,因为vector在插入扩展的时候,会找一片新空间将数据拷贝过去,

缺点:

相比较数组而言,链表所占用的空间较大,遍历消耗的额外时间较多


构造函数


list中的构造函数与vector一样,有四个构造函数

list< T >;//;默认构造函数
list(beg,end);//将迭代器beg到end之间的数据拷贝到本身
list(size_t n,T elem);//将n个elem赋值给本身
list(const list &l);//将l的元素拷贝到本身


使用:


#include<iostream>
#include<list>
using namespace std;
void print(list<int>& l)
{
  for (list<int>::iterator b=l.begin(); b != l.end(); b++)
  {
  cout << *b << " ";
  }
  cout << endl;
}
void test1()
{
  list<int> l;
  list<int> l1(10, 1);
  print(l1);
  list<int>l2(l1);
  print(l2);
  list <int>l3(l1.begin(), l1.end());
  print(l3);
}
int main()
{
  test1();
  return 0;
}

0a2653c851af460fa595bd959398a8f1.png


赋值函数


list中的赋值操作与vector中也是一样的,有三种

list& operator=(const list &l);//操作符重载
assign(beg,end);//将迭代器beg到end的数据拷贝到本身
assign(int n,T elem);//将n个elem拷贝到本身


使用:


#include<iostream>
#include<list>
using namespace std;
void print(list<int>& l)
{
  for (list<int>::iterator b=l.begin(); b != l.end(); b++)
  {
  cout << *b << " ";
  }
  cout << endl;
}
void test1()
{
  list<int> l(10, 1);
  print(l);
  list<int> l1;
  l1 = l;
  print(l1);
  list<int> l2;
  l2.assign(l1.begin(),l1.end());
  print(l2);
  list<int> l3;
  l3.assign(10, 2);
  print(l3);
}
int main()
{
  test1();
  return 0;
}

0eacb84100b54626af849e6b562bf92a.png


交换函数


与vector一样,可以利用swap函数进行交换

swap(list< T > &l);//将l的数据和本身进行交换


使用:


#include<iostream>
#include<list>
using namespace std;
void print(list<int>& l)
{
  for (list<int>::iterator b=l.begin(); b != l.end(); b++)
  {
  cout << *b << " ";
  }
  cout << endl;
}
void test1()
{
  cout << "交换前" << endl;
  list<int> l(10, 1);
  print(l);
  list<int> l1;
  l1.assign(10, 2);
  print(l1);
  cout << "交换后" << endl;
  l.swap(l1);
  print(l);
  print(l1);
}
int main()
{
  test1();
  return 0;
}

2d65d23f6d4748949b924e4057485923.png


容器和大小操作


list比vector少一个容器大小,因为list的空间不是连续的,数据存放方式也与vector不同,有多少元素大小就多少,和vector不一样,所以不需要

size();//返回容器内元素个数
empty();//判断容器是否为空,为空返回真
resize(size_t num);///可以重新指定容器的容量,容量为num,若容器变长,则变长的部分全部补0,若变短,则将超出的部分全部删除
reszie(size_t num,T elem);//可以重新指定容器的容量,容量为num,若容器变长,则变长的部分全部补elem,若变短,则将超出的部分全部删除


使用:


#include<iostream>
#include<list>
using namespace std;
void print(list<int>& l)
{
  for (list<int>::iterator b=l.begin(); b != l.end(); b++)
  {
  cout << *b << " ";
  }
  cout << endl;
}
void test1()
{
  list<int> l;
  if (l.empty())
  {
  cout << "l为空" << endl;
  }
  cout << l.size() << endl;
  l.assign(10, 1);
  print(l);
  l.resize(11);
  print(l);
  l.resize(15, 1);
  print(l);
}
int main()
{
  test1();
  return 0;
}

2e9b90b2ca334476abebe75bafe6eeaa.png


插入操作


list中,有五种插入操作,可以从头部插入,从尾部插入,还有insert的三个重载版本

push_front(T elem);//在头部插入elem
push_end(T elem);//在尾部插入elem
insert(pos,T elem);//在pos的位置插入一个elem,返回新数据的位置
insert(pos, size_t n,T elem);//在pos位置插入n个elem
insert(pos,beg,end);//在pos位置插入迭代器beg到end的数据


使用:


#include<iostream>
#include<list>
using namespace std;
void print(list<int>& l)
{
  for (list<int>::iterator b=l.begin(); b != l.end(); b++)
  {
  cout << *b << " ";
  }
  cout << endl;
}
void test1()
{
  list<int> l;
  l.push_back(2);
  print(l);
  l.push_front(1);
  print(l);
  l.insert(l.end(), 3);
  print(l);
  l.insert(l.begin(), 1,0);
  print(l);
  list<int>::iterator b = l.begin();
  b++;
  l.insert(b, l.begin(), l.end());
  print(l);
}
int main()
{
  test1();
  return 0;
}


删除操作


删除操作有六个,向比较vector多了头部的删除,和一个删除一样元素的删除

pop_back();//删除尾部元素
pop_front();//删除头部元素
clear();//删除全部元素
erase(beg,end);//删除迭代器beg到end之间的数据
erase(pos);//删除迭代器pos位置的数据,返回下一个元素的位置
remove(T elem);//删除容器中所有的elem


使用:


#include<iostream>
#include<list>
using namespace std;
void print(list<int>& l)
{
  for (list<int>::iterator b=l.begin(); b != l.end(); b++)
  {
  cout << *b << " ";
  }
  cout << endl;
}
void test1()
{
  list<int> l;
  for (int i = 0; i < 10; i++)
  {
  l.push_back(i);
  l.push_back(i);
  }
  print(l);
  l.pop_back();
  print(l);
  l.pop_front();
  print(l);
  list<int>::iterator b = l.begin();
  b++; b++; b++;
  l.erase(b);
  print(l);
  list<int>::iterator b1 = l.begin();
  b1++; b1++; b1++;
  l.erase(b1, l.end());
  print(l);
  l.remove(1);
  print(l);
  l.clear();
  print(l);
}
int main()
{
  test1();
  return 0;
}


0eacb84100b54626af849e6b562bf92a.png

0eacb84100b54626af849e6b562bf92a.png


相关文章
|
2天前
|
存储 搜索推荐 C++
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
25 2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
|
2天前
|
存储 C++ 容器
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器1
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
25 5
|
2天前
|
存储 编译器 C++
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
20 2
|
2天前
|
C++
【C++】C++ STL 探索:List使用与背后底层逻辑(三)
【C++】C++ STL 探索:List使用与背后底层逻辑
|
2天前
|
C++
【C++】C++ STL 探索:List使用与背后底层逻辑(二)
【C++】C++ STL 探索:List使用与背后底层逻辑
|
2天前
|
存储 编译器 C++
【C++】C++ STL 探索:List使用与背后底层逻辑(一)
【C++】C++ STL 探索:List使用与背后底层逻辑
|
3月前
|
存储 算法 程序员
C++基础知识(八:STL标准库(Vectors和list))
C++ STL (Standard Template Library标准模板库) 是通用类模板和算法的集合,它提供给程序员一些标准的数据结构的实现如 queues(队列), lists(链表), 和 stacks(栈)等. STL容器的提供是为了让开发者可以更高效率的去开发,同时我们应该也需要知道他们的底层实现,这样在出现错误的时候我们才知道一些原因,才可以更好的去解决问题。
|
4月前
|
安全 Java
java线程之List集合并发安全问题及解决方案
java线程之List集合并发安全问题及解决方案
613 1
|
3月前
|
Java API Apache
怎么在在 Java 中对List进行分区
本文介绍了如何将列表拆分为给定大小的子列表。尽管标准Java集合API未直接支持此功能,但Guava和Apache Commons Collections提供了相关API。
|
3月前
|
运维 关系型数据库 Java
PolarDB产品使用问题之使用List或Range分区表时,Java代码是否需要进行改动
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。