一、定义
list:双向链表,适用于频繁插入和删除元素的场景。
STL中的list是一种动态数组,也就是双向链表的数据结构,它具有以下特点:
- 动态增长:当list中的元素数量超过当前容量时,它会自动增加容量。
- 插入和删除:插入和删除元素的速度比数组快得多,因为它不需要移动元素。
- 顺序访问:由于list是一个双向链表,因此可以从任意位置插入或删除元素,也可以按照顺序访问所有元素。
- 逆序访问:由于list是一个双向链表,因此可以反向访问所有元素。
二、 数据结构
template <class T, class Allocator = allocator<T>>
class list
{
protected:
struct _Node { // Node代表链表中的一个节点
T _Myval; // 节点的数据域
_Node* _Next; // 指向前一个节点的指针
_Node* _Prev; // 指向后一个节点的指针
};
typedef _Node _Nodeptr;
typedef typename Allocator::template rebind<_Node>::other _Alnode;
_Alnode _Al; // 链表的存储器分配器
_Nodeptr _Myhead; // 链表的第一个节点
_Nodeptr _Mylast; // 链表的最后一个节点
size_type _Mysize; // 链表中节点的数量
public:
// 其他的成员函数...
};
//在这个结构中,_Nodeptr是一个内部类型,它是一个指针,指向_Node类型的对象。
//_Alnode也是一个内部类型,它是_Allocator类型的重新绑定,用来分配和释放节点的空间。
//_Myhead和_Mylast分别指向链表的第一个节点和最后一个节点,_Mysize表示链表中节点的数量。
三、具体使用
1.头文件:
#include <list>
2.创建list:
std::list<int> myList; // 创建一个整数类型的双向链表
3.插入元素:
使用 push_back()
和 push_front()
方法在链表的末尾和开头插入元素:
myList.push_back(1); // 在链表末尾插入元素
myList.push_front(2); // 在链表开头插入元素
插入指定位置:使用advance函数移动it迭代器,然后根据迭代器插入:
#include <iostream>
#include <list>
#include <string>
using namespace std;
int main() {
list<int> myList = { 1,2,3,4,5 };
list<int>::iterator it = myList.begin();
advance(it, 2);//将迭代器移动到索引2的位置
myList.insert(it,30);
// 遍历剩余的元素
for (int value : myList) {
cout << value << " ";
}
return 0;
}
4.访问元素
使用迭代器可以访问链表中的元素:
std::list<int>::iterator it;
for (it = myList.begin(); it != myList.end(); ++it) {
std::cout << *it << " ";
}
5.删除元素
使用 erase()
方法删除特定位置的元素:
myList.erase(myList.begin()); // 删除第一个元素
5.1 删除指定位置的元素:
#include <iostream>
#include <list>
int main() {
list<int> myList = { 1,2,3,4,5 };
list<int>::iterator it = myList.begin();
advance(it,2);//将迭代器移动到索引2的位置
myList.erase(it);
// 遍历剩余的元素
for (int value : myList) {
cout << value << " ";
}
return 0;
}
#include <iostream>
#include <vector>
#include <list>
using namespace std;
int main() {
//1.创建双向链表list
list<int> myList;
//2.添加元素
myList.push_back(5);
myList.push_back(6);
myList.push_back(7);
myList.push_front(1);
//3.使用迭代器遍历list
//先声明一个遍历list的迭代器
list<int>::iterator it;
for (it = myList.begin(); it != myList.end();++it) {
cout << *it << endl;
}
//4.删除元素
myList.erase(myList.begin());//删除位置0的元素
return 0;
}
综合示例:
在C++中管理动态数据集合时,
std::list
可以是一个有用的容器。以下是一个使用std::list
的示例,模拟了一个任务列表:
#include <iostream>
#include <list>
#include <string>
using namespace std;
struct Task {
int id;
string description;
Task(int i, const string& desc) : id(i), description(desc) {}
};
int main() {
list<Task> taskList;//用自定义Task数据结构创建list
// 添加任务
taskList.push_back(Task(1, "完成作业"));
taskList.push_back(Task(2, "写报告"));
taskList.push_back(Task(3, "购物"));
taskList.push_back(Task(4, "锻炼"));
// 遍历任务列表
cout << "任务列表:" << endl;
for (const Task& task : taskList) {
cout << "Task " << task.id << ": " << task.description << endl;
}
// 完成任务
list<Task>::iterator it = taskList.begin();
while (it != taskList.end()) {
if (it->id == 2) {
it = taskList.erase(it); // 删除Task 2
}
else {
++it;
}
}
cout << "\n更新后的任务列表:" << endl;
for (const Task& task : taskList) {
cout << "Task " << task.id << ": " << task.description << endl;
}
return 0;
}
其他常见操作
size()
: 获取链表的大小。empty()
: 检查链表是否为空。pop_back()
: 移除链表末尾的元素。pop_front()
: 移除链表开头的元素。splice()
: 将一个链表的元素插入到另一个链表。sort()
: 对链表进行排序。reverse()
: 反转链表。
关注我,为大家持续分享更多的内容,让学习变得更简单,与君共勉,共同成长
。 也可以关注我的公众号CoderSong,
查看更多精彩文章。