当前位置: 首页 > news >正文

C++STL容器:链表介绍与使用

目录

  • 一、链表概念介绍
  • C++中链表的实现与使用
    • 1. 手写链表的定义(无方法)
    • 2.STL库容器: list (双向链表)与 forward_list (单向链表)
      • list
        • list构造方法
        • list增、删、查
        • list的正向与逆向迭代器
        • list 的特殊方法

一、链表概念介绍

 链表是一种通过指针串连起来的数据结构,一个链表节点分为数据域(用来存储数据),和指针域(存储指向下一个(或上一个)结点的地址指针)。根据结构特点可以分为:单向链表、双向链表和循环链表三类:

  1. 单向链表
    代码随想录:单向链表 单向链表就是链表的结点仅含指向后继的指针(next),也就是说后一个数据的指针只能通过前一个数据找到。(单向链表尾部指向空指针)
  2. 双向链表
    代码随想录:双向链表
     双向链表的结点含指向前驱(prev)和后继(next)的指针,适用于需要双向遍历的操作。(双向链表头节点的前驱以及尾节点的后继指向空指针)
  3. 循环链表!

     循环链表就是尾结点指针指向头结点的链表,形成闭环。

 链表的优点:

  • 动态内存分配‌:结点在运行时动态生成,无需预先指定大小,各个节点地址分散(数组是连续的)
  • 高效插入/删除‌:时间复杂度为** O(1)**(数组为O(n))(仅修改指针)。

 链表的缺点:

  • 低效随机访问‌:查找元素需遍历,时间复杂度 O(n)(数组为O(1))。
  • 空间开销‌:需额外空间存储指针,内存利用率低于数组

C++中链表的实现与使用

1. 手写链表的定义(无方法)

//单链表
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){}
};

2.STL库容器: list (双向链表)与 forward_list (单向链表)

list

 list是双向链表结构,每个节点包含前驱(prev)和后继(next)两个指针。对比之前STL容器vector,list少了不能按索引查找数据,多了可以轻松在头部插入数据,其它的方法也都比较类似,用于存储不需要经常访问的数据
 使用需要包含头文件#include<list>并且`using namespace std;

list构造方法

由之前基础知识介绍可知,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());
list增、删、查
//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 <algorithm> 
#include <list>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的正向与逆向迭代器

list是双向链表,因此除了正向迭代器(begin(),end())外,还有逆向迭代器(rbegin(),rend())。逆向迭代器和正向迭代器的区别在于:

  1. begin()指向开头的元素,而rbegin()指向最后一个元素。
  2. 对于操作符++来说,begin()是向后移动,rbegin()是向前。即逆向迭代的++等于正向迭代的--
std::list<int> lst = {10, 20, 30};
for (auto rit = lst.rbegin(); rit != lst.rend(); ++rit) {std::cout << *rit << " ";  // 输出:30 20 10
}
// 逆向迭代器 ++ 实际调用正向迭代器的 --

对于forward_list,没有逆向迭代器

list 的特殊方法
  1. sort()
std::list<int> lst = {30, 10, 20};
lst.sort();  // 默认升序排序,结果为 {10, 20, 30}
  1. splice
     std::list的splice()方法是链表特有的高效节点转移操作,通过直接修改指针实现元素移动,无需拷贝或内存分配。splice(要插入的位置,要插入的链表,要插入链表的元素位置(默认为整体))
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}
http://www.lqws.cn/news/578899.html

相关文章:

  • Linux 日志监控工具对比:从 syslog 到 ELK 实战指南
  • 【PHP】.Hyperf 框架-collection 集合数据(内置函数归纳-实用版)
  • PHP学习笔记(十二)
  • 【Java面试】10GB,1GB内存,如何排序?
  • 时序数据库IoTDB监控指标采集与可视化指南
  • HTML中的<div>元素
  • 云效DevOps vs Gitee vs 自建GitLab的技术选型
  • docker安装MySQL,创建MySQL容器
  • APP 内存测试--Android Profiler实操(入门版)
  • 【解析】 微服务测试工具Parasoft SOAtest如何为响应式架构助力?
  • 2025年数字信号、计算机通信与软件工程国际会议(DSCCSE 2025)
  • [免费]微信小程序停车场预约管理系统(Springboot后端+Vue3管理端)【论文+源码+SQL脚本】
  • Instrct-GPT 强化学习奖励模型 Reward modeling 的训练过程原理实例化详解
  • 【Cyberstrikelab】lab2
  • 百胜软件获邀走进华为,AI实践经验分享精彩绽放
  • 使用 C++ 和 OpenCV 构建驾驶员疲劳检测软件
  • C++ STL之string类
  • 如何让宿主机完全看不到Wi-Fi?虚拟机独立联网隐匿上网实战!
  • Webpack优化详解
  • 赋能低压分布式光伏“四可”建设,筑牢电网安全新防线
  • 爬虫详解:Aipy打造自动抓取代理工具
  • UI前端与数字孪生融合新趋势:智慧医疗的可视化诊断辅助
  • 2025年XXE攻击全面防御指南:从漏洞原理到智能防护实践
  • python 利用socketio(WebSocket协议)实现轻量级穿透方案
  • GO 语言学习 之 Map
  • PyTorch 中 nn.Linear() 参数详解与实战解析(gpt)
  • K8s环境下基于Nginx WebDAV与TLS/SSL的文件上传下载部署指南
  • 极易搭建的自助Git服务Gogs
  • LeetCode 594. Longest Harmonious Subsequence
  • Hyperledger Fabric 入门笔记(二十一)Fabric V2.5 使用K8S部署测试网络