class template
前言
- 本文内容:C++ STL list
- 所属专栏:C/C++ | 全面理解C++ STL标准模板库
- 作者主页:紫荆鱼
- 创作时间:2022-1-3
- 小小提示:文章很长,十分详细,建议先收藏
返回目录(建议收藏):全面理解C++ STL标准模板库
定义:list是序列容器,允许在序列内的任何地方进行恒定时间插入和擦除操作,以及双向迭代。
列表容器被实现为双向链表;双向链表可以将它们包含的每个元素存储在不同且不相关的存储位置。排序是通过与指向它前面元素的链接和指向它后面元素的链接的每个元素的关联在内部保持的。
template < class T, class Alloc = allocator<T> > class list;
参数解释:
T
:成员类型list::value_type。Alloc
:用于定义存储分配模型的分配器对象的类型。
头文件:
#include
注
:(1)(2)(3)(4)为C++98标准,(5)(6)为C++11新标准
//构造一个空容器,没有元素。
explicit list(const allocator_type& alloc=allocator_type());
例子:std::list<int> first;
//构造一个包含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);
//构造一个包含与范围[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());
例子2: int myints[] = {16,2,77,29};
std::list<int> fifth (myints, myints + sizeof(myints) /
sizeof(int) );
//以相同的顺序构造一个容器,其中包含x中每个元素的副本。
list (const list& x);
list (const list& x, const allocator_type& alloc);
例子: std::list<int> fourth (third);
//构造一个获取x元素的容器。
//如果指定了alloc并且与x的分配器不同,则移动元素。
//否则,不会构造任何元素(它们的所有权直接转移)。
//x处于未指定但有效的状态。
list (list&& x);
list (list&& x, const allocator_type& alloc);
例子:std::list<std::string> words8(std::move(words6));
//以相同的顺序构造一个容器,其中包含il中每个元素的副本。
list (initializer_list<value_type> il,
const allocator_type& alloc = allocator_type());
例子:std::list<std::string> words10
{"the", "frogurt", "is", "also", "cursed"};
//(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 << ' ';
}
//在列表容器的末尾,在其当前最后一个元素之后添加一个新元素。
do {
std::cin >> myint;
mylist.push_back (myint);
} while (myint);
//移除列表容器中的最后一个元素,有效地将容器大小减一。
while (!mylist.empty())
{
sum+=mylist.back();
mylist.pop_back();
}
//在列表的开头插入一个新元素,就在其当前第一个元素之前
mylist.push_front (200);
mylist.push_front (300);
//在列表的开头删除一个元素,就在其当前第一个元素之前
while (!mylist.empty())
{
std::cout << ' ' << mylist.front();
mylist.pop_front();
}
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);
公共成员函数
//begin功能:将迭代器返回到开头(公共成员函数)
//end功能:返回迭代器结束(公共成员函数)
for(std::list<int>::iterator it=mylist.begin();
it != mylist.end(); ++it)
rbegin和begin区别: rbegin指向成员end指向的元素之前的元素,即list最后一个元素。
rend和end区别: 指向列表容器中第一个元素之前的理论元素(被认为是它的反向端)
如下图
:
//rbegin功能:返回反向迭代器以反向开始。
//rend功能:返回反向迭代器以反向结束。
for (std::list<int>::reverse_iterator rit=mylist.rbegin();
rit!=mylist.rend(); ++rit)
std::cout << ' ' << *rit;
⬛区别:返回类型为迭代器
//cbegin功能:返回指向容器中第一个元素的const_iterator。
//cend功能:返回指向容器中最后一个元素的 const_iterator
for (auto it = mylist.cbegin(); it != mylist.cend(); ++it)
std::cout << ' ' << *it;
注
:结合(2)(3)的特点:反向+迭代器
//返回一个const_reverse_iterator指向容器中的最后一个元素
//返回一个const_reverse_iterator指向容器中第一个元素之前的理论元素
for(auto rit=mylist.crbegin(); rit!=mylist.crend();++rit)
std::cout << ' ' << *rit;
注
:功能直观,不做解释
//判断list是否非空,求和
while (!mylist.empty())
{
sum += mylist.front();
mylist.pop_front();
}
//输出大小size
for (int i=0; i<10; i++) myints.push_back(i);
std::cout << "1. size: " << myints.size() << '\n';
//如果小于最大size,就继续resize,resize重置size
if (i<mylist.max_size()) mylist.resize(i);
//front:返回对列表容器中第一个元素的引用
//back:返回对列表容器中最后一个元素的引用。
mylist.front() -= mylist.back();
std::cout<< mylist.front()<<mylist.back();
clear:从列表容器中移除所有元素(已销毁),并保留大小为0的容器。
mylist.clear();
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);
swap:交换内容
std::list<int> first (3,100);
std::list<int> second (5,200);
first.swap(second);
assign:将新内容分配给列表容器,替换其当前内容,并相应地修改其大小。
first.assign (7,100);
second.assign (first.begin(),first.end());
int myints[]={1776,7,4};
first.assign (myints,myints+3);
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());
// 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());
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() );
}
从数据结构角度看
很感谢你的阅读,如有帮助给个赞吧,谢谢大家!