解析C++ STL容器list区别于Python的list

class template

std::list

前言

  • 本文内容C++ STL list
  • 所属专栏:C/C++ | 全面理解C++ STL标准模板库
  • 作者主页:紫荆鱼
  • 创作时间:2022-1-3
  • 小小提示:文章很长,十分详细,建议先收藏

返回目录(建议收藏):全面理解C++ STL标准模板库


STL list目录

  • std::list
  • 0.什么是list
  • 1.list原理
  • 2.list构造函数-定义list
    • (1) 默认构造函数
    • (2) 填充构造函数
    • (3) 范围构造器
    • (4) 复制构造函数(和用分配器复制)
    • (5) 移动构造函数(和分配器一起移动)
    • (6) 初始化列表构造函数
  • 3.列表list的输出
    • (1)通过迭代器输出
  • 4.list增加和删除内容
    • (1)list::push_back和list::pop_back
    • (2)list::push_front 和 list::pop_front
    • (3)list::insert 和list::erase
  • 5.迭代器
    • (1)list::begin 和 list::end
    • (2)list::rbegin 和 list::rend
    • (3)list::cbegin 和 list::cend
    • (4)list::crbegin 和 list::crend
  • 6.list容量Capacity
    • (1)list::empty
    • (2)list::size
    • (3)list::max_size
  • 7.元素访问函数
    • (1)list::front 和 list::back
  • 8.其他修饰符
    • (1)list::clear
    • (2)list::resize
    • (3)list::swap
    • (4)list:assign
  • 9.list操作
    • (1)拼接list::splice
    • (2)删除重复值list::unique
    • (3)排序list::sort
  • 10.Python和C++的list比较

0.什么是list

定义list是序列容器允许在序列内的任何地方进行恒定时间插入和擦除操作,以及双向迭代。
列表容器被实现为双向链表;双向链表可以将它们包含的每个元素存储在不同且不相关的存储位置。排序是通过与指向它前面元素的链接和指向它后面元素的链接的每个元素的关联在内部保持的。
解析C++ STL容器list区别于Python的list_第1张图片

1.list原理

template < class T, class Alloc = allocator<T> > class list;

参数解释

  1. T:成员类型list::value_type。
  2. Alloc:用于定义存储分配模型的分配器对象的类型。

头文件

#include 

2.list构造函数-定义list

(1)(2)(3)(4)为C++98标准,(5)(6)为C++11新标准

(1) 默认构造函数

//构造一个空容器,没有元素。
explicit list(const allocator_type& alloc=allocator_type());
例子:std::list<int> first;

(2) 填充构造函数

//构造一个包含n个元素的容器。每个元素都是val的副本(如果提供)。
explicit list (size_type n);
         list (size_type n, const value_type& val,
                const allocator_type& alloc =
  		 allocator_type());
例子:std::list<int> second (4,100);

(3) 范围构造器

//构造一个包含与范围[first,last)一样多的元素的容器
//每个元素都从该范围内的相应元素以相同的顺序安放构造。
template <class InputIterator>
		list (InputIterator first, InputIterator last,
        const allocator_type& alloc = allocator_type());  
例子1:std::list<int> third (second.begin(),second.end());
例子2int myints[] = {16,2,77,29};
std::list<int> fifth (myints, myints + sizeof(myints) / 
					  sizeof(int) );

(4) 复制构造函数(和用分配器复制)

//以相同的顺序构造一个容器,其中包含x中每个元素的副本。
list (const list& x);
list (const list& x, const allocator_type& alloc);
例子: std::list<int> fourth (third);

(5) 移动构造函数(和分配器一起移动)

//构造一个获取x元素的容器。
//如果指定了alloc并且与x的分配器不同,则移动元素。
//否则,不会构造任何元素(它们的所有权直接转移)。
//x处于未指定但有效的状态。
list (list&& x);
list (list&& x, const allocator_type& alloc);
例子:std::list<std::string> words8(std::move(words6));

(6) 初始化列表构造函数

//以相同的顺序构造一个容器,其中包含il中每个元素的副本。
list (initializer_list<value_type> il,
     const allocator_type& alloc = allocator_type());
例子:std::list<std::string> words10 
{"the", "frogurt", "is", "also", "cursed"};

3.列表list的输出

不能通过计数器+索引[ ]来实现输出
在这里插入图片描述

(1)通过迭代器输出

//(1)迭代器输出常用形式
void my_print(std::list<int> &li)
{
	for(std::list<int>::iterator it=li.begin();it!=li.end();it++)
	{
		std::cout<<(*it)<<" ";
	}
	std::cout<<std::endl;
}
//(2)通过auto/typedef/type alias获得迭代器类型
void my_print(std::list<int> &li)
{
	for (auto i = li.begin(); i != li.end(); i++)
	{
    	std::cout << *i << ' ';
	}
	std::cout<<std::endl;
}
//(3)使用range-base,原理类似(2)
void my_print(std::list<int> &li)
{
	for (auto i : li)
    std::cout << i << ' ';
}

以上三种输出方式输出结果
解析C++ STL容器list区别于Python的list_第2张图片


4.list增加和删除内容

(1)list::push_back和list::pop_back

//在列表容器的末尾,在其当前最后一个元素之后添加一个新元素。
do {
    std::cin >> myint;
    mylist.push_back (myint);
} while (myint);

//移除列表容器中的最后一个元素,有效地将容器大小减一。 
while (!mylist.empty())
{
   sum+=mylist.back();
   mylist.pop_back();
}

(2)list::push_front 和 list::pop_front

//在列表的开头插入一个新元素,就在其当前第一个元素之前
mylist.push_front (200);
mylist.push_front (300);

//在列表的开头删除一个元素,就在其当前第一个元素之前
while (!mylist.empty())
{
    std::cout << ' ' << mylist.front();
    mylist.pop_front();
}

(3)list::insert 和list::erase

insert通过在指定位置的元素之前插入新元素来扩展容器
erase从列表容器中删除单个元素 ( position ) 或一系列元素 ( [first,last) )。

std::list<int> mylist;
std::list<int>::iterator it;

mylist.insert (it,10);    // 1 10 2 3 4                 
mylist.insert (it,2,20);  // 1 10 20 20 2 3 4 5        ^

std::vector<int> myvector (2,30);
mylist.insert (it,myvector.begin(),myvector.end());
// 1 10 20 30 30 20 2 3 4 5
//删除it1位置的元素
mylist.erase (it1);
//删除[it1,it2)区间的元素
mylist.erase (it1,it2);

5.迭代器

公共成员函数

(1)list::begin 和 list::end

//begin功能:将迭代器返回到开头(公共成员函数)
//end功能:返回迭代器结束(公共成员函数)
for(std::list<int>::iterator it=mylist.begin();
	it != mylist.end(); ++it)

(2)list::rbegin 和 list::rend

rbegin和begin区别: rbegin指向成员end指向的元素之前的元素,即list最后一个元素。
rend和end区别: 指向列表容器中第一个元素之前的理论元素(被认为是它的反向端)
如下图
解析C++ STL容器list区别于Python的list_第3张图片

//rbegin功能:返回反向迭代器以反向开始。
//rend功能:返回反向迭代器以反向结束。
for (std::list<int>::reverse_iterator rit=mylist.rbegin(); 
	rit!=mylist.rend(); ++rit)
    std::cout << ' ' << *rit;

(3)list::cbegin 和 list::cend

‍⬛区别返回类型为迭代器

//cbegin功能:返回指向容器中第一个元素的const_iterator。
//cend功能:返回指向容器中最后一个元素的 const_iterator
for (auto it = mylist.cbegin(); it != mylist.cend(); ++it)
    std::cout << ' ' << *it;

(4)list::crbegin 和 list::crend

结合(2)(3)的特点:反向+迭代器

//返回一个const_reverse_iterator指向容器中的最后一个元素
//返回一个const_reverse_iterator指向容器中第一个元素之前的理论元素
for(auto rit=mylist.crbegin(); rit!=mylist.crend();++rit)
    std::cout << ' ' << *rit;

6.list容量Capacity

:功能直观,不做解释

(1)list::empty

//判断list是否非空,求和
 while (!mylist.empty())
  {
     sum += mylist.front();
     mylist.pop_front();
  }

(2)list::size

//输出大小size
for (int i=0; i<10; i++) myints.push_back(i);
  std::cout << "1. size: " << myints.size() << '\n';

(3)list::max_size

//如果小于最大size,就继续resize,resize重置size
if (i<mylist.max_size()) mylist.resize(i);

7.元素访问函数

(1)list::front 和 list::back

//front:返回对列表容器中第一个元素的引用
//back:返回对列表容器中最后一个元素的引用。
mylist.front() -= mylist.back();
std::cout<< mylist.front()<<mylist.back();

8.其他修饰符

(1)list::clear

clear从列表容器中移除所有元素(已销毁),并保留大小为0的容器。

mylist.clear();

(2)list::resize

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

//n:新容器大小,以元素数表示
//val:如果n大于当前容器大小,则将其内容复制到添加元素的对象。
//如果未指定,则使用默认构造函数。
void resize (size_type n, value_type val = value_type());
//例子
mylist.resize(5);
mylist.resize(8,100);
mylist.resize(12);

(3)list::swap

swap交换内容

std::list<int> first (3,100);
std::list<int> second (5,200);

first.swap(second);

(4)list:assign

assign将新内容分配给列表容器,替换其当前内容,并相应地修改其大小。

first.assign (7,100);
second.assign (first.begin(),first.end());

int myints[]={1776,7,4};
first.assign (myints,myints+3);

9.list操作

(1)拼接list::splice

mylist1.splice (it, mylist2);     
mylist2.splice (mylist2.begin(),mylist1, it);// "it" is now invalid.

it = mylist1.begin();
std::advance(it,3); // "it" points now to 30

mylist1.splice ( mylist1.begin(), mylist1, it, mylist1.end());
  

(2)删除重复值list::unique

// a binary predicate implemented as a function:
bool same_integral_part (double first, double second)
{ return ( int(first)==int(second) ); }

// a binary predicate implemented as a class:
struct is_near {
  bool operator() (double first, double second)
  { return (fabs(first-second)<5.0); }
};

mylist.unique();
mylist.unique (same_integral_part);
mylist.unique (is_near());

(3)排序list::sort

mylist.sort();
mylist.sort(compare_nocase);

// comparison, not case sensitive.
bool compare_nocase (const std::string& first, const std::string& second)
{
  unsigned int i=0;
  while ( (i<first.length()) && (i<second.length()) )
  {
    if (tolower(first[i])<tolower(second[i])) return true;
    else if (tolower(first[i])>tolower(second[i])) return false;
    ++i;
  }
  return ( first.length() < second.length() );
}


10.Python和C++的list比较

从数据结构角度看

  • STL: list 双向链表
  • Python:list 类似于数组array

很感谢你的阅读,如有帮助给个赞吧,谢谢大家!

你可能感兴趣的:(C/C++,容器,c++,list,stl)