【數據結構】勵志大廠版·初級(二刷復習)雙鏈表

前引:今天學習的雙鏈表屬于鏈表結構中最復雜的一種(帶頭雙向循環鏈表),按照安排,我們會先進行復習,如何實現雙鏈表,如基本的頭插、頭刪、尾刪、尾插,掌握每個細節,隨后進行例題練習,幫助我們了解它的實際挑戰,前面的實現只是了解它結構的入門,當然只有打好基礎才是最重要的,小編會仔細講解它的各個環節,正文開始~?

目錄

知識點速覽

雙鏈表的實現

節點結構

設置哨兵節點

?開辟節點

?尾插

尾刪

頭插

頭刪

?在目標節點前面插入

在目標節點后面插入

練習題說明


知識點速覽

雙鏈表的實現

今天咱們來復習一下最復雜的鏈表結構——帶頭雙向循環鏈表。根據字面意思我們大概可以詳細想象出來它的特點,首先有一個哨兵節點來充當頭節點,其次是循環雙向的,邏輯結構如下圖:

它較與單鏈表的結構里面多了一個指針,指向它的前一個節點,以此達到雙向。針對哨兵節點:

哨兵節點一般不存儲任何數據,?不僅使用方便,可以簡化插入刪除的操作(不用傳二級指針),所有操作無需去處理哨兵節點,邏輯統一,最后可以減少空指針異常

這里的循環是根據節點的空間結構而來的:頭節點->prev=尾節點,尾節點->next=頭節點

節點結構

較單鏈表而言只多加了一個指針,用來指向自身的前一個節點。這里小編用 tpedef 重定義了一下數據類型,方便以后進行維護。

typedef int Plastic;typedef struct DoubleList
{//數據域Plastic data;//前指針域struct DoubleList* prev;//后指針域struct DoubleList* next;
}DoubleList;
設置哨兵節點

哨兵節點的數據域一般不存儲數據,但是它之后的鏈表節點需要給一個數據作為參數開辟節點,所以小編在這里將二者分開,給哨兵節點單獨設置一個函數來開辟空間。開始時頭指針指向哨兵節點,哨兵節點前后指針應該指向自己,已達到雙向循環結構

//設置哨兵節點
DoubleList* pphead = Sentry();
//設置哨兵節點
DoubleList* Sentry()
{//開辟節點DoubleList* newnode = (DoubleList*)malloc(sizeof(DoubleList));//判斷空間有效性if (newnode == NULL){printf("哨兵節點開辟失敗\n");return NULL;}//初始化newnode->next = newnode;newnode->prev = newnode;return newnode;
}
?開辟節點

開辟節點還是和單鏈表一樣,傳一個數據給它就行了

這里需要注意:初始化開辟的節點時應該是前后指向自己的,如下圖:

//新增節點
DoubleList* Newnode(Plastic data)
{//開辟節點DoubleList* newnode = (DoubleList*)malloc(sizeof(DoubleList));//判斷空間有效性if (newnode == NULL){printf("節點開辟失敗\n");return NULL;}//初始化newnode->next = newnode;newnode->prev = newnode;newnode->data = data;return newnode;
}
?尾插

尾插需要先找尾,對于雙向循環鏈表而言,頭節點的前一個節點就是它的尾。然后再插入新增的節點,連接? next? 與? prev? 的關系即可

注意:尾插不用判斷鏈表是否存在啊,因為我們這里有哨兵節點,直接找尾、插入即可

//尾插
void Tail_insert(DoubleList* pphead, Plastic data)
{//找尾DoubleList* tail = pphead->prev;//開辟節點DoubleList* newnode = Newnode(data);//連接pphead->prev = newnode;newnode->next = pphead;tail->next = newnode;newnode->prev = tail;
}

下面我們通過打印函數來看一下尾插的效果如何:

//打印
void List_Print(DoubleList* pphead)
{//如果只有哨兵節點if (pphead->next == pphead){printf("無元素可以打印\n");return;}//因為如果只有哨兵節點,pphead->next就越界了DoubleList* first = pphead->next;while (first != pphead){printf("%d -> ", first->data);first = first->next;}printf("pphead\n");
}
尾刪

尾刪需要先找尾,然后將頭節點與尾的前一個節點進行連接,再釋放之前標記的尾,思維上并不難

//尾刪
void Tail_deletion(DoubleList* pphead)
{//如果只有頭節點無法刪除if (pphead->prev == pphead){printf("無法刪除\n");return;}//找尾DoubleList* tail = pphead->prev;//找倒數第二個節點DoubleList* cur = pphead->prev->prev;//更新關系,重新連接pphead->prev = cur;cur->next = pphead;free(tail);tail = NULL;
}
頭插

先標記頭節點的下一個節點,然后在頭節點與這個標記的節點中間插入即可,最后更新連接關系

//頭插
void Head_insert(DoubleList* pphead, int data)
{//標記頭節點的下一個節點DoubleList* first = pphead->next;DoubleList* newnode = Newnode(5);//更新連接關系pphead->next = newnode;newnode->next = first;first->prev = newnode;newnode->prev = pphead;
}
頭刪

對于只有哨兵節點的雙鏈表是無法頭刪的,因此需要先進行判斷。其次是標記鏈表的第一個節點、第二個節點,重新確立頭節點和第二個節點的關系,再釋放掉第一個節點

//頭刪
void Head_deletion(DoubleList* pphead)
{//判斷是否只有哨兵節點if (pphead->prev == pphead){printf("無法刪除\n");return;}//標記第一個節點DoubleList* first = pphead->next;//標記第二個節點DoubleList* second = first->next;//重新確立頭節點和第二個節點的關系pphead->next = second;second->prev = first;//釋放第一個節點free(first);first = NULL;
}
?在目標節點前面插入

我們先找到目標節點,然后再標記目標節點前面的一個節點,再確立三者之間的 next 與 prev 的關系,如下圖:

//在目標節點前面插入
void Before_target(DoubleList* pphead, int  data)
{//找目標節點DoubleList* cur = pphead->next;while (cur->data != data){if (cur == pphead){printf("沒有找到\n");return;}cur = cur->next;}//標記cur前面的節點DoubleList* prev = cur->prev;DoubleList* newnode = Newnode(6);//將三者進行連接prev->next = newnode;newnode->prev = prev;newnode->next = cur;cur->prev = newnode;
}
在目標節點后面插入

先找到目標節點,然后標記目標節點后面的一個節點,再確立新增節點、目標節點、標記節點的 next? prev 的關系,與“在目標節點前面插入”很類似

//在目標節點后面插入
void Behind_target(DoubleList* pphead, int data)
{//找目標節點DoubleList* cur = pphead->next;while (cur->data != data){if (cur == pphead){printf("沒有找到\n");return;}cur = cur->next;}//標記cur后面的節點DoubleList* next = cur->next;DoubleList* newnode = Newnode(7);//將三者進行連接cur->next = newnode;newnode->prev = cur;newnode->next = next;next->prev = newnode;
}

練習題說明

一般鏈表題,比如考研、面試、校招會以單鏈表居多,大家可以看我的上一篇文章來學習鏈表題目

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/79995.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/79995.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/79995.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CSS `display` 屬性詳解(完整版)

CSS display 屬性詳解(完整版) 1. 屬性值及特性詳解 display 屬性控制元素的布局類型和生成的框類型,以下是 所有有效值 及其特性: 1.1 基礎類型 值描述布局行為是否生成塊級框典型用途block元素獨占一行,寬度自動撐…

【數據結構 · 初階】- 堆的實現

目錄 一.初始化 二.插入 三.刪除(堆頂、根) 四.整體代碼 Heap.h Test.c Heap.c 我們使用順序結構實現完全二叉樹,也就是堆的實現 以前學的數據結構只是單純的存儲數據。堆除了存儲數據,還有其他的價值——排序。是一個功能…

qt.tlsbackend.ossl: Failed to load libssl/libcrypto.

我的環境是windows,QT6.3.2(msvc2019_64/mingw_64) 出錯原因 QT沒有正確加載OpenSSL。 解決過程 1、確保安裝的有openssl。 文章結尾有個注意,是其他方式安裝過openssl,環境變量有,但是QT找不到的問題。…

【Linux】用戶權限

shell命令 1. Linux本質上是一個操作系統,但是一般的用戶不能直接使用它,而是需要通過外殼程序shell,來與Linux內核進行溝通。 2. shell的簡單定義:命令行解釋器。主要包含以下作用: 將使用者的命令翻譯給核心處理。將…

賽靈思 XC7K325T-2FFG900I FPGA Xilinx Kintex?7

XC7K325T-2FFG900I 是 Xilinx Kintex?7 系列中一款工業級 (I) 高性能 FPGA,基于 28 nm HKMG HPL 工藝制程,核心電壓標稱 1.0 V,I/O 電壓可在 0.97 V–1.03 V 之間靈活配置,并可在 –40 C 至 100 C 溫度范圍內穩定運行。該器件提供…

【題解-Acwing】847. 圖中點的層次

題目:847. 圖中點的層次 題目描述 給定一個 n 個點 m 條邊的有向圖,圖中可能存在重邊和自環。 所有邊的長度都是 1,點的編號為 1~n。 請你求出 1 號點到 n 號點的最短距離,如果從 1 號點無法走到 n 號點,輸出 ?1 。 輸入 第一行包含兩個整數 n 和 m。 接下來 m 行…

css圖片設為灰色

使用filter方式將圖片設置為灰色 普通圖片使用&#xff1a;filter: saturate(0); 純白圖片使用&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"width…

【Luogu】動態規劃一

P5414 [YNOI2019] 排序 - 洛谷 思路&#xff1a; 可以想到對于任意一個需要換位置的數字&#xff0c;我們不可能換兩次及以上&#xff0c;那么這題就可以轉化為求一個最大和的最長不遞減子序列&#xff0c;最后的答案就是眾和減去這個最大和 代碼&#xff1a; #include <…

什么是管理思維?

管理思維是指在管理活動中形成的系統性、戰略性和創造性的思考方式&#xff0c;幫助個人或團隊更高效地達成目標。它不僅適用于企業管理&#xff0c;也適用于個人成長、項目執行和復雜問題解決。以下是關于管理思維的核心內容&#xff1a; 一、管理思維的核心特征 1. 系統性思…

利用TCP+多進程技術實現私聊信息

服務器&#xff1a; import socket from multiprocessing import Process from threading import Threaduser_dic {}def send_recv(client_conn, client_addr):while 1:# 接收客戶端發送的消息res client_conn.recv(1024).decode("utf-8")print("客戶端發送…

Hbuilder 上的水印相機實現方案 (vue3 + vite + hbuilder)

效果 思路 通過 live-pusher 這個視頻推流的組件來獲取攝像頭拿到視頻的一幀圖片之后&#xff0c;跳轉到正常的 vue 頁面&#xff0c;通過 canvas 來處理圖片水印 源碼 live-pusher 這個組件必須是 nvue 的 至于什么是 nvue&#xff0c;看這個官方文檔吧 https://uniapp.dcl…

Spark,IDEA編寫Maven項目

IDEA中編寫Maven項目 1.打開IDEA新建項目2.選擇java語言&#xff0c;構建系統選擇Maven 3.IDEA中配置Maven 注&#xff1a;這些文件都是我們老師幫我們在網上找了改動后給我們的&#xff0c;大家可自行在網上查找 編寫代碼測試HDFS連接 1.在之前創建的pom.xml文件中添加下…

初識Redis · C++客戶端set和zset

目錄 前言&#xff1a; set sadd sismember smembers spop scard sinter sinterstore zset zadd zrange zcard zrem zrank zscore 前言&#xff1a; 前文我們已經介紹了string list hash在Redis-plus-plus的使用&#xff0c;本文我們開始介紹set和zset在redis-plus-pl…

sed命令筆記250419

sed命令筆記250419 sed&#xff08;Stream Editor&#xff09;是 Linux/Unix 系統中強大的流編輯器&#xff0c;主要用于對文本進行過濾和轉換&#xff08;按行處理&#xff09;。它支持正則表達式&#xff0c;適合處理文本替換、刪除、插入等操作。以下是 sed 的詳細解析&…

ubuntu-24.04.2-live-server-arm64基于cloud-init實現分區自動擴容(LVM分區模式)

1. 環境 虛擬機鏡像ISO&#xff1a;ubuntu-24.04.2-live-server-arm64.iso 2. 定制cloud-init鏡像 2.1 安裝OS 基于ubuntu-24.04.2-live-server-arm64.iso&#xff0c;通過virt-manager安裝操作系統&#xff0c;語言建議選擇英文&#xff0c;分區選擇基于LVM的自動分區&…

vue3專題1------父組件中更改子組件的屬性

理解 Vue 3 中父組件如何引用子組件的屬性是一個很重要的概念。 這里涉及到 defineExpose 和 ref 這兩個關鍵點。 方法&#xff1a;使用 defineExpose 在子組件中暴露屬性&#xff0c;然后在父組件中使用 ref 獲取子組件實例并訪問暴露的屬性。 下面我將詳細解釋這個過程&…

數據倉庫分層架構解析:從理論到實戰的完整指南??

數據倉庫分層是構建高效數據體系的核心方法論。本文系統闡述ODS、DWD、DWS、ADS四層架構的設計原理&#xff0c;結合電商用戶行為分析場景&#xff0c;詳解各層功能及協作流程&#xff0c;并給出分層設計的原則與避坑指南&#xff0c;幫助讀者掌握分層架構的落地方法。 一、為什…

從零搭建一套前端開發環境

一、基礎環境搭建 1.NVM(Node Version Manager)安裝 簡介 nvm&#xff08;Node Version Manager&#xff09; 是一個用于管理多個 Node.js 版本的工具&#xff0c;允許開發者在同一臺機器上輕松安裝、切換和使用不同版本的 Node.js。它特別適合需要同時維護多個項目&#xff…

計算機組成原理筆記(十六)——4.1基本算術運算的實現

計算機中最基本的算術運算是加法運算&#xff0c;加、減、乘、除運算最終都可以歸結為加法運算。 4.1.1加法器 一、加法器的基本單元 加法器的核心單元是 全加器&#xff08;Full Adder, FA&#xff09;&#xff0c;而所有加法器都由 半加器&#xff08;Half Adder, HA&…

利用Qt創建一個模擬問答系統

界面&#xff1a; 添加了聊天顯示區域&#xff08;QTextEdit&#xff09; 添加了發送按鈕和清空對話按鈕 優化了布局和窗口大小添加了時間戳顯示 2、功能&#xff1a; 支持實時對話可以清空對話歷史 支持按回車發送消息 添加了簡單的關鍵詞匹配響應系統 交互體驗&#x…