數據結構(8)雙向鏈表

目錄

一、概念與結構

?二、雙向鏈表的實現

1、初始化

2、尾插?

3、頭插

4、尾刪?

5、頭刪?

6、在指定位置之后插入結點?

?7、刪除指定位置的結點

三、完整參考代碼?

一、概念與結構

????????這里的雙向鏈表是指帶頭的的雙向循環鏈表,這里的“帶頭”和之前所說的“頭結點”是兩個概念,帶頭鏈表里的頭結點,實際是“哨兵位”。哨兵位節點不存儲任何有效元素,只是起一個“站崗放哨”的作用。和單鏈表一樣,雙向鏈表也是由一個一個的結點組成,但這里的結點由三個部分組成:保存的數據+指向下一個節點的指針+指向前一個節點的指針。

typedef int LTDataType;
typedef struct ListNode
{LTDataType data;struct ListNode* next;struct ListNode* prev;
}LTNode;
LTNode* LTBuyNode(LTDataType x)
{LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));if (newnode == NULL){perror("malloc fail!");exit(1);}newnode->data = x;newnode->next = newnode->prev = newnode;return newnode;
}

注:當單鏈表為空時,指向第一個結點的指針為空;當雙向鏈表為空時,鏈表中只有一個頭結點~?

?二、雙向鏈表的實現

1、初始化

雙向鏈表的初始化有兩種方式,這里更推薦使用第二種。

第一種:

void LTInit(LTNode** pphead)
{assert(pphead);*pphead = LTBuyNode(-1);
}

第二種:

LTNode* LTInit()
{LTNode* phead = LTBuyNode(-1);return phead;
}

2、尾插?

?尾插這里的參數要注意傳的是一級指針而不是二級指針,因為我們在初始化時給頭結點申請了一塊空間(假設這塊空間的地址是0x339),尾插操作改變的只是頭結點的prev指針和next指針的值,并沒有修改頭結點的地址。那為什么之前的單向鏈表傳的是二級指針呢?單鏈表的第一個結點phead初始情況下為NULL,現在向單鏈表中尾插一個結點(假設該結點的地址是0x300)。此時phead的值從NULL變為了0x300,phead的值發生了改變,所以傳的是二級指針。

在尾插操作中,需要修改的就是頭結點,尾結點和新插入的結點。對于新節點來說,我們需要修改prev和next指針,對于頭結點要修改prev,尾結點要修改next。在雙向鏈表中,我們不用遍歷整個鏈表來找到尾結點,因為可以直接通過頭結點的prev指針來找到尾結點。

//尾插
void LTPushBack(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = LTBuyNode(x);//phead   phead->prev(尾結點)   newnodenewnode->prev = phead->prev;newnode->next = phead;phead->prev->next = newnode;phead->prev = newnode;
}

3、頭插

頭插是在第一個結點之前插入新節點,而不是在頭結點之前插入。

void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = LTBuyNode(x);//phead  newnode  phead->nextnewnode->next = phead->next;newnode->prev = phead;phead->next->prev = newnode;phead->next = newnode;
}

4、尾刪?

進行刪除操作之前,首先要判斷雙向鏈表是否為空。

//只有一個頭節點的情況下,雙向鏈表為空
bool LTEmpty(LTNode* phead)
{assert(phead);return phead->next == phead;
}

//尾刪
void LTPopBack(LTNode* phead)
{assert(!LTEmpty(phead));LTNode* del = phead->prev;//phead  del->prev  delphead->prev = del->prev;del->prev->next = phead;free(del);del = NULL;
}

5、頭刪?

//頭刪
void LTPopFront(LTNode* phead)
{assert(!LTEmpty(phead));LTNode* del = phead->next;//phead  del  del->nextphead->next = del->next;del->next->prev = phead;free(del);del = NULL;
}

6、在指定位置之后插入結點?

//在pos位置之后插入數據
void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* newnode = LTBuyNode(x);//pos  newnode  pos->nextnewnode->next = pos->next;newnode->prev = pos;pos->next->prev = newnode;pos->next = newnode;
}

?7、刪除指定位置的結點

//刪除pos位置的結點
void Erase(LTNode* pos)
{assert(pos);//pos->prev  pos  pos->nextpos->next->prev = pos->prev;pos->prev->next = pos->next;free(pos);pos = NULL;
}

三、完整參考代碼?

List.h

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>//雙向鏈表的結構
typedef int LTDataType;
typedef struct ListNode
{LTDataType data;struct ListNode* next;struct ListNode* prev;
}LTNode;void LTPrint(LTNode* phead);bool LTEmpty(LTNode* phead);//雙向鏈表的初始化
//void LTInit(LTNode** pphead);LTNode* LTInit();//尾插
void LTPushBack(LTNode* phead, LTDataType x);//頭插
void LTPushFront(LTNode* phead, LTDataType x);//尾刪
void LTPopBack(LTNode* phead);//頭刪
void LTPopFront(LTNode* phead);LTNode* LTFind(LTNode* phead, LTDataType x);//在pos位置之后插入數據
void LTInsert(LTNode* pos, LTDataType x);//刪除pos位置的結點
void LTErase(LTNode* pos);//傳二級:違背接口一致性
//void LTDestroy(LTNode** pphead);
//傳一級:調用完成之后將實參手動置為NULL(推薦)
void LTDestroy(LTNode* phead);

List.c

#define  _CRT_SECURE_NO_WARNINGS 1
#include "List.h"LTNode* LTBuyNode(LTDataType x)
{LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));if (newnode == NULL){perror("malloc fail!");exit(1);}newnode->data = x;newnode->next = newnode->prev = newnode;return newnode;
}void LTPrint(LTNode* phead)
{LTNode* pcur = phead->next;while (pcur != phead){printf("%d -> ", pcur->data);pcur = pcur->next;}printf("\n");
}//雙向鏈表的初始化
//void LTInit(LTNode** pphead)
//{
//	assert(pphead);
//	*pphead = LTBuyNode(-1);
//}LTNode* LTInit()
{LTNode* phead = LTBuyNode(-1);return phead;
}//尾插
void LTPushBack(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = LTBuyNode(x);//phead   phead->prev(尾結點)   newnodenewnode->prev = phead->prev;newnode->next = phead;phead->prev->next = newnode;phead->prev = newnode;
}//頭插
void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = LTBuyNode(x);//phead  newnode  phead->nextnewnode->next = phead->next;newnode->prev = phead;phead->next->prev = newnode;phead->next = newnode;
}//只有一個頭節點的情況下,雙向鏈表為空
bool LTEmpty(LTNode* phead)
{assert(phead);return phead->next == phead;
}//尾刪
void LTPopBack(LTNode* phead)
{assert(!LTEmpty(phead));LTNode* del = phead->prev;//phead  del->prev  delphead->prev = del->prev;del->prev->next = phead;free(del);del = NULL;
}//頭刪
void LTPopFront(LTNode* phead)
{assert(!LTEmpty(phead));LTNode* del = phead->next;//phead  del  del->nextphead->next = del->next;del->next->prev = phead;free(del);del = NULL;
}LTNode* LTFind(LTNode* phead, LTDataType x)
{assert(phead);LTNode* pcur = phead->next;while (pcur != phead){if (pcur->data == x){return pcur;}pcur = pcur->next;}//沒找到return NULL;
}//在pos位置之后插入數據
void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* newnode = LTBuyNode(x);//pos  newnode  pos->nextnewnode->next = pos->next;newnode->prev = pos;pos->next->prev = newnode;pos->next = newnode;
}//刪除pos位置的結點
void LTErase(LTNode* pos)
{assert(pos);//pos->prev  pos  pos->nextpos->next->prev = pos->prev;pos->prev->next = pos->next;free(pos);pos = NULL;
}void LTDestroy(LTNode* phead)
{LTNode* pcur = phead->next;while(pcur != phead){LTNode* next = pcur->next;free(pcur);pcur = next;}free(phead);phead = NULL;
}

test.c?

#define  _CRT_SECURE_NO_WARNINGS 1
#include "List.h"void test01()
{LTNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPrint(plist);//LTPushFront(plist, 1);//LTPushFront(plist, 2);//LTPopBack(plist);//LTPrint(plist);//LTPopFront(plist);//LTPrint(plist);LTNode* find = LTFind(plist, 3);LTErase(find);LTPrint(plist);LTDestroy(plist);plist = NULL;
}int main()
{test01();return 0;
}

?

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

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

相關文章

【DeepSeek-R1 】分詞系統架構解析

文章目錄 ??前言 ?? 1. SentencePiece Unigram 的核心原理 1.1 算法基礎框架 1.2 核心數學原理 1.3 與BPE/WordPiece的對比 ?? 2. DeepSeek-R1 分詞器實現細節 2.1 詞表結構設計 2.2 關鍵特性實現 ?? 3. 性能優化關鍵技術 3.1 加速策略對比 3.2 編碼過程偽代碼 ?? 4.…

Linux自主實現shell

以下是在Linux操作系統 centos7版本下實現的shell &#xff0c;該shell具備bash的基礎功能&#xff0c;無上下鍵輸入歷史命令功能&#xff0c;刪除字符或命令時按住Ctrl Back #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.…

vue+elementUI上傳圖片至七牛云組件封裝及循環使用

1.效果&#xff08;解決循環組件賦值問題&#xff09; 廢話不多說直接上代碼 2.下載七牛云依賴 npm install qiniu-js # 或者使用 yarn yarn add qiniu-js3.在vue組件中引入 import * as qiniu from qiniu-js4.在components文件夾下創建UploadImg1/uploadImg.vue組件 <templ…

2025年6月電子學會青少年軟件編程(C語言)等級考試試卷(一級)

答案和更多內容請查看網站&#xff1a;【試卷中心 -----> 電子學會 ----> C/C ----> 一級】 網站鏈接 青少年軟件編程歷年真題模擬題實時更新 一、編程題 第 1 題 希望如光 題目描述 在充滿挑戰的生活中&#xff0c;希望往往是支撐人們穿越黑暗的核心力量。這…

拒絕復雜,AI圖表制作簡單化

在信息爆炸的時代&#xff0c;數據可視化已成為傳遞信息的核心手段。無論是職場匯報中的業績分析&#xff0c;還是學術研究里的實驗數據呈現&#xff0c;一張清晰直觀的圖表往往能勝過千言萬語。而 AI 技術的介入&#xff0c;徹底改變了圖表制作的傳統模式 —— 它不僅讓零基礎…

easypoi生成多個sheet的動態表頭的實現

在使用 EasyPOI 導出 Excel 時&#xff0c;生成多個 Sheet 且每個 Sheet 的表頭是動態的&#xff08;即每個 Sheet 的列數和列名可能不同&#xff09;&#xff0c;可以通過如下方式實現&#xff1a;? 實現原理簡述 使用 Workbook workbook ExcelExportUtil.exportExcel(expor…

移除鏈表元素+反轉鏈表+鏈表的中間節點+合并兩個有序鏈表+環形鏈表約瑟夫問題+分割鏈表

一、移除鏈表元素 給你一個鏈表的頭節點 phead 和一個整數 val &#xff0c;請你刪除鏈表中所有滿足 Node.val val 的節點&#xff0c;并返回 新的頭節點 (列表中的節點數目在范圍 [0, 104] 內) 示例&#xff1a;輸入&#xff1a;head [1,2,6,3,4,5,6], val 6 …

vue3+arcgisAPI4示例:軌跡點模擬移動(附源碼下載)

demo源碼運行環境以及配置運行環境&#xff1a;依賴Node安裝環境&#xff0c;需要安裝Node。 運行工具&#xff1a;vscode或者其他工具。 配置方式&#xff1a;下載demo源碼&#xff0c;vscode打開&#xff0c;然后順序執行以下命令&#xff1a; &#xff08;1&#xff09;下載…

Design Compiler:Milkyway庫的創建與使用

相關閱讀 Design Compilerhttps://blog.csdn.net/weixin_45791458/category_12738116.html?spm1001.2014.3001.5482 DC Ultra推出了拓撲模式&#xff0c;在綜合時會對標準單元進行粗布局(Coarse Placement)并使用虛擬布線(Virtual Routing)技術計算互聯延遲&#xff0c;關于拓…

嵌入式教學的云端革命:高精度仿真如何重塑倒車雷達實驗與工程教育——深圳航天科技創新研究院賦能新一代虛實融合實訓平臺

一、嵌入式教學的困境與破局之道 在傳統嵌入式系統教學中&#xff0c;硬件依賴始終是核心痛點。以“倒車雷達實驗”為例&#xff0c;學生需操作STM32開發板、超聲波傳感器、蜂鳴器等硬件&#xff0c;面臨設備損耗、接線錯誤、調試效率低等問題。更關鍵的是&#xff0c;物理硬件…

flutter-boilerplate-project 學習筆記

項目地址&#xff1a; https://github.com/zubairehman/flutter_boilerplate_project/tree/master 樣板包含創建新庫或項目所需的最小實現。存儲庫代碼預加載了一些基本組件&#xff0c;例如基本應用程序架構、應用程序主題、常量和創建新項目所需的依賴項。通過使用樣板代碼…

集成電路學習:什么是CMSIS微控制器軟件接口標準

CMSIS,即Cortex Microcontroller Software Interface Standard(Cortex微控制器軟件接口標準),是由ARM公司與多家不同的芯片和軟件供應商緊密合作定義的一個標準。該標準旨在為基于ARM Cortex處理器的微控制器提供一套與供應商無關的硬件抽象層,從而簡化軟件的開發、重用,…

由淺入深使用LangGraph創建一個Agent工作流

創建一個簡單的工作流&#xff1a;Start ——> 節點1(固定輸入輸出) ——> Endfrom langchain_core.messages import SystemMessage, HumanMessage, AIMessage from langgraph.graph import StateGraph, START, END from typing_extensions import TypedDict from typing…

PL-0功能拓展及基于VSCode的IDE配置

title: PL/0功能拓展及基于VSCode的IDE配置 date: 2024-08-06 22:46:38 tags: 做過的實驗||項目復盤 top: true 概述PL/0語言可以看成PASCAL語言的子集,它的編譯程序是由C語言編寫的編譯解釋執行系統。PL/0能充分展示高級語言的最基本成分。拓展了pl0語言的基礎功能&#xff08…

【低空經濟】大型露天礦區安全生產無人機巡查與管理系統設計

1. 引言 大型露天礦區因其廣闊的作業區域和復雜的環境條件&#xff0c;安全生產管理面臨著嚴峻的挑戰。隨著科技的進步&#xff0c;無人機作為一種現代化的巡查工具&#xff0c;逐漸被應用于礦區的安全生產管理中。無人機具備高效、靈活、成本相對低廉等優點&#xff0c;可以在…

SpringCloud學習第一季-3

目錄 11.服務網關-Gateway新一代網關 一、Gateway概述 1、Gateway是什么 1.1 概述 2、 能干嘛 3、微服務架構中網關在哪里 4、為什么選擇gateway? 4.1 SpringCloud Gateway具有如下特性 4.2 SpringCloud Gateway 與 Zuul的區別 5、Zuul1.x模型 6、gateway模型 二、…

超越邊界:MongoDB 16MB 文檔限制的 pragmatic 解決方案

在軟件開發中&#xff0c;我們選擇的技術棧往往帶有一些固有的設計邊界。對于 MongoDB 而言&#xff0c;其最著名的邊界之一便是 BSON 文檔最大 16MB 的大小限制。在大多數場景下&#xff0c;這個限制是綽綽有余的&#xff0c;它鼓勵開發者設計更為精簡和規范的數據模型。然而&…

深入探討:PostgreSQL正則表達式中的郵政編碼匹配

引言 在處理大量數據時,如何高效地從字符串中提取特定模式的文本,如郵政編碼,是一個常見且具有挑戰性的任務。本文將通過一個具體實例,探討在PostgreSQL中使用正則表達式匹配加拿大郵政編碼的問題,并提供解決方案。 問題描述 我們希望能夠從字符串中提取所有符合加拿大…

集合框架(重點)

第十五天集合框架1.什么是集合 Collections集合Collection&#xff0c;也是一個數據容器&#xff0c;類似于數組&#xff0c;但是和數組是不一樣的。集合是一個可變的容器&#xff0c;可以隨時向集合中添加元素&#xff0c;也可以隨時從集合中刪除元素。另外&#xff0c;集合還…

深度學習核心:神經網絡-激活函數 - 原理、實現及在醫學影像領域的應用

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家、CSDN平臺優質創作者&#xff0c;高級開發工程師&#xff0c;數學專業&#xff0c;10年以上C/C, C#,Java等多種編程語言開發經驗&#xff0c;擁有高級工程師證書&#xff1b;擅長C/C、C#等開發語言&#xff0c;熟悉Java常用開發…