【初探數據結構】鏈表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.pswp.cn/bicheng/72545.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/72545.shtml
英文地址,請注明出處:http://en.pswp.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…