C++小记 -链表
链表
文章目录
- 链表
- 链表基础理论
- 链表的类型
- 单链表
- 双链表
- 循环链表
- 链表的存储方式
- 链表的定义
- 链表的操作
- 添加节点
- 删除节点
- 性能分析
- 构建链表
- 删除节点(内存泄漏的坑)
- 1.直接移除
- 2.使用虚拟头结点
- 3.delete指针后,要将指针置为NULL!!
- 完整代码示例
链表基础理论
什么是链表,链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。
链表的入口节点称为链表的头结点也就是head。
链表的类型
单链表

双链表

单链表中的指针域只能指向节点的下一个节点。
双链表:每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点。
双链表 既可以向前查询也可以向后查询。
循环链表
循环链表,顾名思义,就是链表首尾相连。
循环链表可以用来解决约瑟夫环

链表的存储方式
数组是在内存中是连续分布的,但是链表在内存中可不是连续分布的。
链表是通过指针域的指针链接在内存中各个节点。
所以链表中的节点在内存中不是连续分布的 ,而是散乱分布在内存中的某地址上,分配机制取决于操作系统的内存管理。

这个链表起始节点为2, 终止节点为7, 各个节点分布在内存的不同地址空间上,通过指针串联在一起。
链表的定义
// 单链表
struct ListNode {int val; // 节点上存储的元素ListNode *next; // 指向下一个节点的指针ListNode(int x) : val(x), next(NULL) {} // 节点的构造函数
};
有同学说了,我不定义构造函数行不行,答案是可以的,C++默认生成一个构造函数。
但是这个构造函数不会初始化任何成员变量,下面我来举两个例子:
通过自己定义构造函数初始化节点:
ListNode* head = new ListNode(5);
使用默认构造函数初始化节点:
ListNode* head = new ListNode();
head->val = 5;
所以如果不定义构造函数使用默认构造函数的话,在初始化的时候就不能直接给变量赋值!
链表的操作
添加节点

删除节点
删除D节点,如图所示:

delete root;
只要将C节点的next指针 指向E节点就可以了。
那有同学说了,D节点不是依然存留在内存里么?只不过是没有在这个链表里而已。
是这样的,所以在C++里最好是再手动释放这个D节点,释放这块内存。
性能分析

数组在定义的时候,长度就是固定的,如果想改动数组的长度,就需要重新定义一个新的数组。
链表的长度可以是不固定的,并且可以动态增删, 适合数据量不固定,频繁增删,较少查询的场景。
构建链表
// 数组构造链表
ListNode* construct_array(const vector<int>& vec) {if (vec.empty()) return nullptr;ListNode* head = new ListNode(vec[0]);ListNode* cur = head;for (int i = 1; i < vec.size(); i++) {cur->next = new ListNode(vec[i]);cur = cur->next;}cur->next = NULL;return head;
}
删除节点(内存泄漏的坑)
1.直接移除
ListNode* removeElements1(ListNode* head, int val) {// 删除头节点while (head!=NULL && head->val == val){ListNode* tmp = head;head = head->next;delete tmp;tmp = NULL;}// 删除非头节点ListNode* cur = head;while (cur != NULL && cur->next != NULL){if (cur->next->val == val){ListNode* tmp = cur->next;cur->next = cur->next->next;delete tmp;tmp = NULL;}else{cur = cur->next;}}return head;
}
2.使用虚拟头结点
ListNode* removeElements2(ListNode* head, int val) {ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点dummyHead->next = head; // 将虚拟头结点指向head,这样方便后面做删除操作ListNode* cur = dummyHead;while (cur->next != NULL) {if (cur->next->val == val) {ListNode* tmp = cur->next;cur->next = cur->next->next;delete tmp;tmp = NULL; }else {cur = cur->next;}}head = dummyHead->next;delete dummyHead;return head;
}
3.delete指针后,要将指针置为NULL!!
在delete指针后,将指针置为NULL。例如:delete tmp; tmp = NULL;
在delete指针后,将指针置为NULL。例如:delete tmp; tmp = NULL;
在delete指针后,将指针置为NULL。例如:delete tmp; tmp = NULL;
不然会发生内存泄漏!!!
不然会发生内存泄漏!!!
不然会发生内存泄漏!!
完整代码示例
#include <iostream>
#include <vector>
using namespace std;// 单链表
struct ListNode
{int val; // 节点上存储的元素ListNode *next; // 指向下一个节点的指针ListNode() : val(NULL), next(NULL){} // 节点的构造函数ListNode(int x) : val(x), next(NULL){} // 节点的构造函数
};// 数组构造链表
ListNode* construct_array(const vector<int>& vec) {if (vec.empty()) return nullptr;ListNode* head = new ListNode(vec[0]);ListNode* cur = head;for (int i = 1; i < vec.size(); i++) {cur->next = new ListNode(vec[i]);cur = cur->next;}cur->next = NULL;return head;
}// 添加节点
void append(ListNode* head, int value){if (!head){head = new ListNode(value);}else{ListNode* cur = head;while (cur->next){cur = cur->next;}cur->next = new ListNode(value);}
}/* 删除节点
在delete指针后,将指针置为NULL。例如:delete tmp; tmp = NULL;
在delete指针后,将指针置为NULL。例如:delete tmp; tmp = NULL;
在delete指针后,将指针置为NULL。例如:delete tmp; tmp = NULL;
*/
ListNode* removeElements(ListNode* head, int val) {// 删除头节点while (head != NULL && head->val == val){ListNode* tmp = head;head = head->next;delete tmp;tmp = NULL;}// 删除非头节点ListNode* cur = head;while (cur != NULL && cur->next != NULL){if (cur->next->val == val){ListNode* tmp = cur->next;cur->next = cur->next->next;delete tmp;tmp = NULL;}else{cur = cur->next;}}return head;
}// 打印链表
void printList(ListNode* head){ListNode* cur = head;while (cur){cout << cur->val << " ";cur = cur->next;}cout << endl;
}int main() {vector<int> arry = { 1, 3, 3, 4, 5 };ListNode* head = construct_array(arry);printList(head);append(head, 6);printList(head);head = removeElements(head, 3);printList(head);system("PAUSE");return 0;
}
相关文章:
C++小记 -链表
链表 文章目录 链表链表基础理论链表的类型单链表双链表循环链表 链表的存储方式链表的定义链表的操作添加节点删除节点 性能分析构建链表删除节点(内存泄漏的坑)1.直接移除2.使用虚拟头结点3.delete指针后,要将指针置为NULL!&…...
网络协议学习DAY1
1.网络协议模型: OSI协议模型 应用层 实际发送的数据 表示层 发送的数据是否加密 会话层 是否建立会话连接 传输层 数据传输的方式(数据报、流式) 网…...
vue3中全局变量的定义和获取
在vue项目中,我们知道vue2定义全局变量是在main.js文件将变量挂载到vue.prototype.name"lisi",在页面通过this.name去调用。但是在vue3中,这个定义全局变量有所改变: const app createApp(App) app.config.globalProp…...
1.2 数据模型 数据库系统概论
目录 1.2.1 两类数据模型 1.2.2 概念模型 1.信息世界中的基本概念 (1)实体 (2)属性 (3)码 (4)实体型 (5)实体集 (6)联系 2.…...
C#中openFileDialog 对话框不在最顶层,TopMost的异常情况
重点!!!若 当前窗体this的TopMost是false,可以设置为true,这样打开的对话框就是最顶层 /// <summary> /// 设置窗体TopMost,缺点和其他程序ide有冲突。例如VS有断点的调试会卡死 /// </summary&g…...
信息安全与阿里云等保三级方案实践总结
信息安全在当今数字化时代变得至关重要,企业和组织需要采取有效措施来保护其数据和信息资产。阿里云作为中国领先的云服务提供商,提供了等保三级方案,帮助用户满足国家信息安全等级保护的要求。本文将探讨信息安全和阿里云等保三级方案的重要…...
嵌入式学习记录——线程
线程基本概念: 线程:线程是一个轻量级的进程,位于进程空间内部,一个进程中可以创建多个线程 1.线程创建: 线程独占栈空间,文本段、数据段和堆区与进程共享 2.线程调度: 与进程调度是一样的 宏观并行,微观串行 3.线程消亡: 与进程消亡是一样的 4.进程和线程…...
同步服务器操作系统公网仓库到本地 _ 统信UOS _ 麒麟KYLINOS
原文链接:同步服务器操作系统公网仓库到本地 | 统信UOS | 麒麟KYLINOS 在如今快速发展的信息技术时代,维护和更新服务器操作系统变得越来越重要。无论是为了提高安全性、增加新功能还是提升系统稳定性,同步公网源仓库到本地都是一个关键步骤。…...
【数仓】flume常见配置总结,以及示例
相关文章 【数仓】基本概念、知识普及、核心技术【数仓】数据分层概念以及相关逻辑【数仓】Hadoop软件安装及使用(集群配置)【数仓】Hadoop集群配置常用参数说明【数仓】zookeeper软件安装及集群配置【数仓】kafka软件安装及集群配置【数仓】flume软件安…...
统计信息锁定
在导入成功后我要收集下这些表的信息,结果发现好几张表都没法收集,用DBMS_STATS包显示ORA-20005:object statistics are locked (stattype ALL),用Analyze命令显示ORA-38029: 对象统计信息已锁定。 解决办法很明确&a…...
光猫改为bridge模式
注意事项: 改成桥接模式后,光猫将不再拨号上网,建议提前记录自己的宽带账号,打10010申请修改自己的宽带密码。 光猫改好桥接之后,把宽带账号和密码输入到负责拨号上网的终端设备中,完成宽带PPPOE拨号设置。…...
回溯算法01-组合(Java)
1.组合 题目描述 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1: 输入:n 4, k 2 输出: [[2,4],[3,4],[2,3],[1,2],[1,3],[1,4]]示例 2: 输入&#x…...
初始网络 --- 网络基础
目录 0、 前言 1、 计算机网络发展背景 1.1. 局域网(LAN) && 广域网(WAN) 2、 认识并理解协议 3、 初始网络协议 3.1. 协议分层 4、 TCP/IP 五层(或四层)模型 4.1. 简单了解TCP/IP层状体系 4.2. TCP/IP协议层状结构和计算机层状结构的关系 5、 OSI七层模型 …...
在Linux/Ubuntu/Debian中计算MD5,SHA256的方法
MD5(消息摘要算法 5)和 SHA-256(安全哈希算法 256 位)等流行的哈希算法广泛用于从任意数据生成固定大小的哈希值或校验和。 以下是这些算法及其计算方式的简要概述: MD5(消息摘要算法5)&#x…...
mybatis mysql insert 主键id为空
错误示范 java代码设置了param参数,但是sql 字段没有带上参数,例如 void insertV2(Param("historyDO") HistoryDO historyDO); <insert id"insertDuplicate" parameterType"com.test.entity.HistoryDO"keyProperty&…...
批次大小对ES写入性能影响初探
问题背景 ES使用bulk写入时每批次的大小对性能有什么影响?设置每批次多大为好? 一般来说,在Elasticsearch中,使用bulk API进行批量写入时,每批次的大小对性能有着显著的影响。具体来说,当批量请求的大小增…...
c语言十大核心用法
当然,以下是十个关于 C 语言用法的代码示例: 指针的基本用法: #include <stdio.h>int main() {int num 10;int *ptr;ptr #printf("The value of num is: %d\n", *ptr);return 0; }结构体的使用: #in…...
网页打开慢,这锅该谁背?
一、背景 工作中扯皮说不可避免且非常常见的事情. 开发与产品、开发和测试、前端和后端都会产生扯皮现象。今天要聊的一个问题就是前后端之间的扯皮问题。 网页打开太慢或者点击了某个按钮发现数据很久才显示出来,这个锅谁背? 做开发不能无凭据地胡乱甩锅, 我们…...
题目 1538: 蓝桥杯-格子位置
题目描述: 输入三个自然数N,i,j (1< i< N,1< j< N),输出在一个N*N格的棋盘中,与格子(i,j)同行、同列、同一对角线的所有格子的位置。 样例解释…...
第十三届蓝桥杯嵌入式省赛程序设计详细题解
第十三届蓝桥杯嵌入式省赛题目相对于第十二届较为简单,没有那么多串口的数据处理以及判断! 第十三届省赛主要是制作一个可由串口设置密码的密码锁。本实验中,我们将用到LED模块、按键模块、串口模块、定时器的PWM模块以及官方会提供源码的LC…...
FPGA小白也能懂:用Verilog在Xilinx Vivado里驱动HC-SR04超声波模块(附完整仿真)
FPGA实战:从零构建超声波测距系统(VerilogVivado全流程解析) 第一次接触FPGA时,最让人头疼的莫过于如何将抽象的硬件描述语言转化为实际可运行的电路。去年我在指导电子设计竞赛时,发现学生们对超声波模块的应用需求很…...
python教育培训机构教务信息管理系统vue
目录功能模块分析学员管理课程管理教师管理财务管理数据统计与分析系统管理技术实现要点前端(Vue)后端(Python)数据交互示例(API设计)扩展功能建议项目技术支持源码获取详细视频演示 :文章底部获…...
Python异步服务部署与无服务器架构实践指南
Python异步服务部署与无服务器架构实践指南 【免费下载链接】uvicorn An ASGI web server, for Python. 🦄 项目地址: https://gitcode.com/GitHub_Trending/uv/uvicorn 在云原生应用开发领域,Python异步服务部署正成为构建高性能后端系统的首选方…...
【深度学习新浪潮】如何安全、可靠地使用OpenClaw?
前言 当下AI智能体赛道飞速发展,OpenClaw凭借本地私有化部署、系统级实操能力、多模型兼容的核心优势,成为开发者、办公人群追捧的自动化工具。它可以调度浏览器、执行文件操作、运行终端脚本、串联多步骤业务流程,真正实现大语言模型从对话交互到落地执行的跨越。 但很多…...
ECDICT开源英汉词典数据库:构建高可用分布式语言服务的完整技术方案
ECDICT开源英汉词典数据库:构建高可用分布式语言服务的完整技术方案 【免费下载链接】ECDICT Free English to Chinese Dictionary Database 项目地址: https://gitcode.com/gh_mirrors/ec/ECDICT ECDICT是一个完全免费的开源英汉词典数据库,为开…...
Protocol Buffer 入门:跨平台的高效序列化神器
🔥个人主页:Milestone-里程碑 ❄️个人专栏: <<力扣hot100>> <<C>><<Linux>> <<Git>><<MySQL>> 🌟心向往之行必能至 目录 一、什么是 Protobuf? 二、序列化与反…...
从零到一:UniApp前端网页托管与自定义域名配置实战指南
1. 从零开始:UniApp前端网页托管全流程解析 第一次接触UniApp前端网页托管时,我也被各种专业术语搞得晕头转向。经过几个项目的实战,我发现这套流程其实就像租房子:你得先有个门牌号(域名),再找…...
利用Cosmos-Reason1-7B进行技术文档(LaTeX/Markdown)自动摘要与校对
利用Cosmos-Reason1-7B进行技术文档(LaTeX/Markdown)自动摘要与校对 你有没有过这样的经历?面对一份几十页的技术论文或者一份复杂的实验报告,光是通读一遍就要花掉大半天时间。更别提还要从中提炼核心观点,或者逐字逐…...
别再手动汉化了!用Docker Compose持久化配置Greenbone GVM中文界面(附yml文件修改)
持久化配置Greenbone GVM中文界面的Docker Compose实战指南 对于安全工程师和运维人员来说,Greenbone Vulnerability Management(GVM)是进行漏洞扫描的利器。但每次重启容器后都需要重新配置中文界面,这无疑增加了维护成本。本文…...
探索Lumerical建模计算可调谐光学手性
Lumerical建模计算可调谐光学手性在光学领域,可调谐光学手性是一个极具吸引力的研究方向。而Lumerical作为一款强大的光学仿真软件,为我们深入探究这一领域提供了有力工具。 什么是可调谐光学手性 光学手性简单来说,描述的是光与物质相互作用…...
