🐔博主码云
🐔博主主页
目录
🐓list简介
list是C++ STL中的一个双向链表容器,可以存储任何类型的元素。它提供了一组成员函数,可以在链表的任何位置插入和删除元素,也可以在链表的任何位置访问元素。与数组不同,list不需要连续的内存空间,因此可以动态地分配和释放内存。在插入和删除元素时,不会影响其他元素的位置,因此可以保持链表中元素的相对顺序。list支持双向迭代器,可以在正向和反向方向遍历链表。list是STL中的一个标准容器,可以在头文件中找到。它的常用操作包括创建list、插入元素、删除元素、访问元素、遍历std::list和其他常用函数等。
总的来说,list具有如下几个特性:
- 元素按照它们在链表中的顺序存储,因此可以高效地在任何位置插入和删除元素。
- 不支持随机访问,只能通过遍历链表来访问元素。
- 支持双向迭代器,可以在正向和反向方向遍历链表。
- 与数组不同,list不需要连续的内存空间,因此可以动态地分配和释放内存。
- 在插入和删除元素时,不会影响其他元素的位置,因此可以保持链表中元素的相对顺序。
🐓list使用
🐤list构造函数
函数名 | 特性 |
---|---|
默认构造函数:list() | 该构造函数创建一个空的list对象。 |
拷贝构造函数:list(const list& l) | 该构造函数创建一个与l相同的list对象。 |
带有元素数量和元素值的构造函数:list(size_type n, const value_type& val = value_type()) | 该构造函数创建一个包含n个元素,每个元素的值都为val的list对象。 |
带有迭代器范围的构造函数:list(InputIterator first, InputIterator last) | 该构造函数创建一个包含[first, last)范围内的元素的list对象。其中,first和last是迭代器,用于指定要复制到新list中的元素范围。 |
示例代码:
#include <iostream>
#include <list>
using namespace std;
void print(list<int> ls)
{
for (auto e : ls)
{
cout << e << ' ';
}
cout << endl;
}
int main()
{
list<int> ls;
print(ls);
list<int> ls2(10, 6);
print(ls2);
list<int> ls3(ls2);
print(ls3);
list<int> ls4(ls2.begin(), ls2.end());
print(ls4);
return 0;
}
运行结果:
🐤list迭代器
list提供了双向迭代器(bidirectional iterator),可以用于遍历list中的元素。list的迭代器定义在头文件中,可以使用list::iterator和list::const_iterator来表示可变和不可变的迭代器。
list的迭代器支持以下操作:
函数声明 | 特性 |
---|---|
begin()和end() | 分别返回指向list首元素和尾元素下一个位置的迭代器。 |
rbegin()和rend() | 分别返回指向list尾元素和首元素前一个位置的逆向迭代器。 |
示例代码:
#include <iostream>
#include <list>
using namespace std;
int main()
{
string arr = "abcdefg";
list<char> ls(arr.begin(), arr.end());
list<char>::iterator it = ls.begin();
list<char>::reverse_iterator rit = ls.rbegin();
while (it != ls.end())
{
cout << *it << ' ';
it++;
}
cout << endl;
while (rit != ls.rend())
{
cout << *rit << ' ';
rit++;
}
cout << endl;
return 0;
}
运行结果:
🐤list capacity
list的容量是动态变化的,因此并没有capacity()函数来返回list的容量。以下是list的容量相关函数:
函数 | 说明 |
---|---|
size() | 返回list中元素的数量。 |
max_size() | 返回list最多可以容纳的元素数量,这个数量取决于系统的限制。 |
empty() | 判断list是否为空,如果list为空,则返回true,否则返回false。 |
示例代码:
#include <iostream>
#include <list>
using namespace std;
int main()
{
string arr = "abcdefg";
list<char> ls(arr.begin(), arr.end());
cout << "是否为空:" << ls.empty() << endl;
cout << "最大存储数量:" << ls.max_size() << endl;
cout << "当前存储数量:" << ls.size() << endl;
return 0;
}
运行结果:
🐤list element access
list提供了一些用于访问元素的函数,如下
函数名 | 说明 |
---|---|
front() | 返回list中第一个元素的引用。 |
back() | 返回list中最后一个元素的引用。 |
示例代码:
#include <iostream>
#include <list>
using namespace std;
int main()
{
string arr = "abcdefg";
list<char> ls(arr.begin(), arr.end());
char front = ls.front();
char back = ls.back();
cout << front << " " << back << endl;
return 0;
}
运行结果:
🐤list modifiers
在C++中,list提供了多种操作函数来方便地对链表进行操作。其中,list中的modifiers函数主要用于修改链表中的元素,包括插入、删除和替换等操作。
以下是常用的list modifiers函数:
函数 | 说明 |
---|---|
push_back | 在链表的末尾插入一个元素。 |
push_front | 在链表的头部插入一个元素。 |
insert | 在指定位置插入一个元素。 |
erase | 删除指定位置的元素。 |
clear | 清空链表中的所有元素。 |
pop_back | 删除链表末尾的元素。 |
pop_front | 删除链表头部的元素。 |
swap | 用于交换两个链表的内容 |
示例代码:
#include <iostream>
#include <list>
using namespace std;
template<typename T>
void Print(list<T> ls)
{
for (const auto& e : ls)
{
cout << e << ' ';
}
cout << endl;
}
int main()
{
list<char> ls;
ls.push_back('A');
ls.push_back('B');
ls.push_back('C');
Print(ls);
ls.push_front('1');
ls.push_front('2');
ls.push_front('3');
Print(ls);
ls.pop_back();
ls.pop_front();
Print(ls);
string arr = "abcd";
ls.insert(ls.begin(), 'M');
ls.insert(ls.end(), arr.begin(), arr.end());
ls.insert(ls.begin(), 3, 'O');
Print(ls);
list<char> ls2(ls);
ls.erase(ls.begin());
Print(ls);
ls.swap(ls2);
Print(ls);
Print(ls2);
ls2.clear();
ls.erase(ls.begin(), ls.end());
Print(ls);
Print(ls2);
return 0;
}
运行结果:
🐤list的迭代器失效
在使用list容器时,需要注意到删除节点会导致迭代器失效的问题。因为list容器的底层实现是双向链表,当我们删除某个节点时,该节点的前后节点会重新建立连接,而被删除节点的迭代器就会失效,指向该节点的迭代器将无法访问该节点,也无法访问其后继节点。
示例代码
#include <iostream>
#include <list>
using namespace std;
int main()
{
list<char> ls = {'a', 'b', 'c', 'd'};
list<char>::iterator it = ls.begin();
while (it != ls.end())
{
if (*it == 'b')
{
ls.erase(it);
}
cout << *it << ' ';
it++;
}
return 0;
}
运行结果:
我们可以先保存指向要删除的节点的迭代器,然后将迭代器指向下一个节点,在进行删除操作。
int main()
{
list<char> ls = {'a', 'b', 'c', 'd'};
list<char>::iterator it = ls.begin();
while (it != ls.end())
{
if (*it == 'b')
{
auto tmp = it++;
ls.erase(tmp);
}
else
{
cout << *it << ' ';
it++;
}
}
return 0;
}
另外,当我们将迭代器保存到外部使用时也会导致迭代器失效。
#include <iostream>
#include <list>
using namespace std;
int main() {
std::list<int> mylist = { 1, 2, 3, 4, 5 };
auto it = mylist.begin();
// 将迭代器保存到外部使用
auto outside_it = it;
// 对list容器进行删除操作
mylist.erase(mylist.begin());
// 使用保存在外部的迭代器访问list容器
std::cout << *outside_it << std::endl;
return 0;
}
🐓总结
list是C++ STL中的一个双向链表容器,可以在任意位置高效地插入和删除元素,不需要像vector那样移动其他元素。总之,list容器是一个高效的双向链表容器,可以在任意位置高效地插入和删除元素,是一个非常实用的容器。