【初探数据结构】链表OJ算法——哨兵位(合并两个有序链表详解)

文章目录

  • 哨兵位(Sentinel Node)的作用
  • 实战演练
    • 思路讲解
    • 详细步骤
      • 1. **处理特殊情况(边界条件)**
      • 2. **创建哨兵节点**
      • 3. **初始化两个指针,遍历两个链表**
      • 4. **合并两个链表**
      • 5. **处理剩余节点**
      • 6. **返回合并后的链表**
    • 完整代码
  • 结语

哨兵位(Sentinel Node)的作用

哨兵位是链表中的一个特殊节点,它并不保存有效数据,只是作为标识存在。使用哨兵位有以下几个好处:

  • 统一处理:哨兵位使得链表的插入和删除操作可以统一处理,无需区分链表为空、头节点或尾节点等特殊情况。
  • 简化代码:避免了空链表的处理、头节点的特殊处理等复杂情况,使得代码更加简洁。

下面我们来实战演练。

实战演练

合并两个有序链表 - 力扣(LeetCode)

这道题的解法很多,这里我们使用最优的方法——双指针遍历

思路讲解

通过两个指针同时遍历两个链表,逐个比较链表中的节点,将较小的节点接到合并后的链表上,直到一个链表遍历完成,再将另一个链表中剩余的部分直接接到结果链表后。

详细步骤

1. 处理特殊情况(边界条件)

if(list1 == NULL)return list2;
if(list2 == NULL)return list1;

如果其中一个链表为空,直接返回另一个链表。这样可以避免后续操作中对空链表的额外处理。

2. 创建哨兵节点

struct ListNode* tail = NULL, *guard = NULL;
guard = tail = (struct ListNode*)malloc(sizeof(struct ListNode));
tail->next = NULL;
  • 创建一个哨兵节点guard,该节点不会保存实际的数据。它的作用是简化链表的操作,特别是头节点的处理。因为如果直接操作链表头节点,可能需要单独判断头节点是否为空或其他边界情况,使用哨兵节点后,我们就可以统一处理所有节点的插入。
  • tail指针用于指向合并链表的尾部。通过这个指针,我们可以方便地将新的节点插入到合并后的链表中。

3. 初始化两个指针,遍历两个链表

struct ListNode* cur1 = list1;
struct ListNode* cur2 = list2;
  • cur1cur2分别指向两个输入链表list1list2的头节点。我们将使用这两个指针遍历两个链表,进行比较并合并。

4. 合并两个链表

while(cur1 && cur2) {if(cur1->val < cur2->val) {tail->next = cur1;cur1 = cur1->next;tail = tail->next;} else {tail->next = cur2;cur2 = cur2->next;tail = tail->next;}
}
  • 这里使用一个while循环,循环条件是cur1cur2都不为空。也就是说,只有当两个链表中都有节点时,才会进入循环。
  • 在循环内部,比较cur1cur2所指向节点的值,选择较小的节点加入到合并后的链表中:
    • 如果cur1的值小于cur2的值,就将cur1节点连接到tailnext上,并将cur1向后移动一个节点。
    • 否则,将cur2节点连接到tailnext上,并将cur2向后移动一个节点。
  • 每次将新的节点连接到tail之后,更新tail指针,指向合并链表的最后一个节点。

5. 处理剩余节点

if(cur1)tail->next = cur1;
if(cur2)tail->next = cur2;
  • 在上面的while循环结束后,可能会有一个链表的节点已经全部被处理完,另一个链表中还有节点没有被合并。
  • 如果cur1指向的链表中还有节点未处理(即cur1不为空),将剩余的cur1节点直接接到合并链表的尾部。
  • 同理,如果cur2指向的链表中还有节点未处理(即cur2不为空),将剩余的cur2节点直接接到合并链表的尾部。

6. 返回合并后的链表

struct ListNode* head = guard->next;
free(guard);
return head;
  • 合并后的链表的头节点是guard->next,因为guard本身是一个哨兵节点,不保存实际的数据。返回guard->next就是合并后的链表的头节点。
  • 最后,释放掉guard节点占用的内存,因为guard节点已经不再需要。

完整代码

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {// 如果list1为空,返回list2if(list1 == NULL)return list2;// 如果list2为空,返回list1if(list2 == NULL)return list1;struct ListNode* tail = NULL, *guard = NULL;struct ListNode* cur1 = list1;struct ListNode* cur2 = list2;// 创建一个哨兵节点guard,方便操作链表头guard = tail = (struct ListNode*)malloc(sizeof(struct ListNode));tail->next = NULL;// 合并两个链表while(cur1 && cur2) {// 判断当前cur1的值与cur2的值,选择较小的节点if(cur1->val < cur2->val) {tail->next = cur1;cur1 = cur1->next;  // 移动cur1指针tail = tail->next;   // 更新tail指针} else {tail->next = cur2;cur2 = cur2->next;  // 移动cur2指针tail = tail->next;   // 更新tail指针}}// 如果cur1还有剩余,连接到tailif(cur1)tail->next = cur1;// 如果cur2还有剩余,连接到tailif(cur2)tail->next = cur2;// 头指针是guard的下一个节点struct ListNode* head = guard->next;// 释放哨兵节点free(guard);return head;
}

结语

如果这道题不用哨兵位,你将会被一个错误搞的焦头烂额——对空指针解引用,不相信的话你可以去试试,你一定会影响深刻的。

通过这道题,是不是觉得哨兵位真的很香?非常省事,特别是这种多链表的联合问题,我们一定要留个心眼。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/72545.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

libcoap在Ubuntu下的编译(基于CMake)

引言 libcoap 是一个开源的轻量级 C 语言库&#xff0c;用于实现 CoAP&#xff08;Constrained Application Protocol&#xff0c;受限应用协议&#xff09;。CoAP 是一种专为资源受限设备设计的轻量级通信协议&#xff0c;适用于物联网&#xff08;IoT&#xff09;和嵌入式系…

命名管道实现传递数据到二进制文件

一 前言&#xff1a; 在做项目的过程中&#xff0c;一般来说我们的信息输入是有固定的端口/来源的&#xff0c;但是在当前的越来越快的开发节奏下&#xff0c;往往会出现输入源还未完全确定的情况下需要我们先实现功能逻辑&#xff0c;信号接受端后面再对接。或者数据接受端和功…

VSCode知名主题带毒 安装量900万次

目前微软已经从 Visual Studio Marketplace 中删除非常流行的主题扩展 Material Theme Free 和 Material Theme Icons&#xff0c;微软称这些主题扩展包含恶意代码。 统计显示这些扩展程序的安装总次数近 900 万次&#xff0c;在微软实施删除后现在已安装这些扩展的开发者也会…

如何快速的解除oracle dataguard

有些时候&#xff0c;我们为了使oracle dg的standby库另做他用&#xff0c;需要解除oracle dataguard数据同步。我本地因为standby库存储出现故障&#xff0c;导致dg存在问题&#xff0c;故需要解除。今天&#xff0c;我们通过使用部分命令&#xff0c;实现dg的快速解除。 1&a…

Windows系统编程(七)HotFixHook

InoolineHook需要读写两次内存&#xff08;先HOOK&#xff0c;再还原&#xff09;&#xff0c;这种Hook方式&#xff0c;性能比较低&#xff0c;具有局限性。今天所讲的HotFixHOOK&#xff08;热补丁&#xff09;是InlineHook的升级版 Win32 API特殊性 Win32API的实现代码有这…

Python Web应用开发之Flask框架——基础

一、前言 在即将开启的 Flask 学习之旅中,为了能够顺利掌握并运用 Flask 进行 Web 开发,您需要具备一定的基础知识,同时了解相应的运行环境。 需要你具备的知识:Python 编程语言、HTML、CSS、HTTP协议、数据库(如:MySQL、MongoDB) 本文所使用的环境:操作系统Windows…

TCP通讯与基于C#TCP通讯,跨窗收发消息Demo

TCP&#xff08;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字节流的传输层通信协议。它广泛应用于互联网中的数据通信&#xff0c;如网页浏览、文件传输、电子邮件等。以下是TCP通信的基本概念和工作原理&#xff1a; 1. TCP的特点 面向连接&#xff1a;通信前…

【有源码】仿DeepSeek问答网站+SpringBoot+VUE3+对接DeepSeek API

今天带来一款优秀的项目&#xff1a;仿DeepSeek问答网站。 功能和官网差不多&#xff0c;也有历史上下文&#xff0c;流失对话等。 本文介绍了系统功能与部署安装步骤&#xff0c;如果您有任何问题&#xff0c;也请联系学姐&#xff0c;偶现在是经验丰富的程序员&#xff01; …

Ubuntu20.04双系统安装及软件安装(七):Anaconda3

Ubuntu20.04双系统安装及软件安装&#xff08;七&#xff09;&#xff1a;Anaconda3 打开Anaconda官网&#xff0c;在右侧处填写邮箱&#xff08;要真实有效&#xff01;&#xff09;&#xff0c;然后Submit。会出现如图示的Success界面。 进入填写的邮箱&#xff0c;有一封Ana…

洛谷 P2142 高精度减法(详解)c++

题目链接&#xff1a;P2142 高精度减法 - 洛谷 1.题目 2.算法原理 解法:模拟列竖式计算的过程 先用字符串读入&#xff0c;然后拆分每一位&#xff0c;逆序放进数组中利用数组&#xff0c;模拟列竖式减法的过程 在这两步之前要多加一步&#xff0c;在模拟解法的过程&#…

在 MyBatis 中,若数据库字段名与 SQL 保留字冲突解决办法

在 MyBatis 中&#xff0c;若数据库字段名与 SQL 保留字冲突&#xff0c;可通过以下方法解决&#xff1a; 目录 一、使用转义符号包裹字段名二、通过别名映射三、借助 MyBatis-Plus 注解四、全局配置策略&#xff08;辅助方案&#xff09;最佳实践与注意事项 一、使用转义符号…

ThreadLocal解析

1. ThreadLocal的定义与核心作用 ThreadLocal是Java中用于实现线程局部变量的工具类。它为每个线程提供独立的变量副本&#xff0c;使得每个线程访问的是自己的数据&#xff0c;从而避免多线程环境下的资源共享问题&#xff0c;实现线程隔离。 例如&#xff0c;解决SimpleDate…

Kafka零拷贝

Kafka为什么适用零拷贝&#xff0c;其他存储结构不适用&#xff1f; Kafka 采用的是日志存储模型&#xff0c;数据通常是顺序写入、顺序读取&#xff0c;并且它的消费模式是 “读完即走”&#xff08;一次性读取并发送给消费者&#xff09;&#xff0c;这与零拷贝的特性完美匹…

微服务组件详解——sentinel

1.启动sentinel&#xff1a; 下载jar sentinel-dashboard-1.8.0.jar 使用以下命令直接运行 jar 包&#xff08;JDK 版本必须≥ 1.8&#xff09;&#xff1a; java -Dserver.port9999 -jar D:\sentinel-dashboard-1.8.0.jar 控制台访问地址&#xff1a;http://localhost:9999…

AI数据分析:deepseek生成SQL

在当今数据驱动的时代&#xff0c;数据分析已成为企业和个人决策的重要工具。随着人工智能技术的快速发展&#xff0c;AI 驱动的数据分析工具正在改变我们处理和分析数据的方式。本文将着重介绍如何使用 DeepSeek 进行自动补全SQL 查询语句。 我们都知道&#xff0c;SQL 查询语…

动态规划01背包问题系列一>目标和

目录 题目分析及优化&#xff1a;状态表示&#xff1a;状态转移方程&#xff1a;初始化&#xff1a;填表顺序&#xff1a;返回值&#xff1a;代码呈现&#xff1a;优化&#xff1a;代码呈现&#xff1a; 题目分析及优化&#xff1a; 状态表示&#xff1a; 状态转移方程&#xf…

Linux 基础---sudo权限 修改文件所属人、用户所属组

sudo 概念&#xff1a;让普通用户使用管理员权限执行一些操作&#xff08;root&#xff09; 在命令前加上sudo 即可 修改文件所属人、所属组

HMC7043和HMC7044芯片配置使用

一,HMC7043芯片 MC7043独特的特性是对14个通道分别进行独立灵活的相位管理。所有14个通道均支持频率和相位调整。这些输出还可针对50 Ω或100 Ω内部和外部端接选项进行编程。HMC7043器件具有RF SYNC功能,支持确定性同步多个HMC7043器件,即确保所有时钟输出从同一时钟沿开始…

【动手实验】TCP半连接队列、全连接队列实战分析

本文是对 从一次线上问题说起&#xff0c;详解 TCP 半连接队列、全连接队列 这篇文章的实验复现和总结&#xff0c;借此加深对 TCP 半连接队列、全连接队列的理解。 实验环境 两台腾讯云服务器 node2&#xff08;172.19.0.12&#xff09; 和 node3&#xff08;172.19.0.15&am…

Springboot整合WebSocket+Redis以及微信小程序如何调用

一、 Springboot整合WebSocket 1. 引入socket依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dependency>引入依赖后需要刷新maven,Websocket的版本默认跟随S…