链表是一种通过指针串连起来的数据结构,一个链表节点分为数据域(用来存储数据),和指针域(存储指向下一个(或上一个)结点的地址指针)。根据结构特点可以分为:单向链表、双向链表和循环链表三类:
链表的优点:
链表的缺点:
//单链表
struct ListNode {
int val; //数据域
ListNode* next; //指针域
ListNode(int val = 0, ListNode* next = nullptr) : val(val), next(next) {}
};
//双链表
struct ListNode{
int val; //数据域
ListNode* prev;//指针域
ListNode* next;//指针域
ListNode(int val=0,ListNode* prev = nullptr,ListNode* next = nullptr):val(val),prev(prev),next(next){}
};
list是双向链表结构,每个节点包含前驱(prev)和后继(next)两个指针。对比之前STL容器vector,list少了不能按索引查找数据,多了可以轻松在头部插入数据,其它的方法也都比较类似,用于存储不需要经常访问的数据。
使用需要包含头文件#include
并且`using namespace std;
由之前基础知识介绍可知,list对象的构造除了不支持初始化为n个空闲空间(链表是动态存储),其它与vector差不多。
//构造
//1. 构造空链表
list<T> L_name;
//2. 初始化为 n个 value
list<T> L_name(n,value);
//3. 拷贝初始化,L2为一个已有链表
list<T> L_name(L2_name);
//4. 迭代器初始化,L1为其它容器
list<T> L_name(L1.begin(),L1.end());
//1.在头部增加/删除元素
L_name.push_front(value); //增加
L_name.pop_front(); //删除
//2. 在尾部增加/删除元素
L_name.push_back(value);//增加
L_name.pop_back();//删除
//3. 在指定位置增加/删除元素
//增加 insert
list<int>::iterator pos = L_name.begin(); //pos一定要是迭代器对象
auto new_it = L_name.insert(pos,value); //在pos位置插入value,返回一个指向当前插入元素的指针,之前的pos仍然指向原来的值
L_name.insert(pos,n,value); //在pos位置插入n个value
//删除 erase
L_name.erase(pos); //删除指定位置的数据
L_name.erase(L_name.begin(),L_name.end()); //删除区间,这里L_name.begin(),L_name.end()仅作演示,表示所有
//删除 remove
L_name.remove(value); //删除等于value的所有元素
//4.查询头部
L_name.front();
//5.查询尾部
L_name.back();
//6.查询其它位置
//链表不像数组那样有下标,因此查询其它位置的数据只能通过迭代的方式进行。
//第一种,通过遍历的方法查询:
for (auto it = lst.begin(); it != lst.end(); ++it) {//这里list的迭代器和vector不一样,不能直接 + 偏移量(链表内存地址不连续)
if (*it == 30) {
std::cout << "Found at position: " << std::distance(lst.begin(), it);
break;
}
}
//第二种,通过find函数查找:
#include
#include
std::list<int> lst = {10, 20, 30};
auto it = std::find(lst.begin(), lst.end(), 20); // 查找值为20的元素
if (it != lst.end()) {
std::cout << "Found: " << *it << std::endl;
}
list是双向链表,因此除了正向迭代器(begin(),end())外,还有逆向迭代器(rbegin(),rend())。逆向迭代器和正向迭代器的区别在于:
++
等于正向迭代的--
std::list<int> lst = {10, 20, 30};
for (auto rit = lst.rbegin(); rit != lst.rend(); ++rit) {
std::cout << *rit << " "; // 输出:30 20 10
}
// 逆向迭代器 ++ 实际调用正向迭代器的 --
对于forward_list,没有逆向迭代器
std::list<int> lst = {30, 10, 20};
lst.sort(); // 默认升序排序,结果为 {10, 20, 30}
std::list<int> lst1{1, 2}, lst2{3, 4};
auto pos = lst1.end();
// 整链转移
lst1.splice(pos, lst2); // lst1={1,2,3,4}, lst2为空
// 单元素转移
lst2.splice(lst2.begin(), lst1, ++lst1.begin()); // lst1={1,3,4}, lst2={2}
// 范围转移
lst1.splice(lst1.begin(), lst1, ++lst1.begin(), lst1.end()); // lst1={3,4,1}