雙向鏈表(數據結構與算法)

請添加圖片描述

????????????????
????????????????
🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿
🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟
🌟🌟 追風趕月莫停留 🌟🌟
🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀🍀
🌟🌟 平蕪盡處是春山🌟🌟
🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟
🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿🌿
????????????????
????????????????

🍋雙向鏈表

  • 🍌雙向鏈表的定義與結構
  • 🍌雙向鏈表增刪查改(有頭+雙向+循環鏈表增刪查改實現)
    • 🍍其它接口
    • 🍍創建返回鏈表的頭結點
    • 🍍雙向鏈表銷毀
    • 🍍雙向鏈表打印
    • 🍍雙向鏈表尾插
    • 🍍雙向鏈表尾刪
    • 🍍雙向鏈表頭插
    • 🍍雙向鏈表頭刪
    • 🍍雙向鏈表查找
    • 🍍雙向鏈表在pos的前面進行插入
    • 🍍雙向鏈表刪除pos位置的節點
  • 🍌雙向鏈表整體代碼的實現

🍌雙向鏈表的定義與結構

在這里插入圖片描述
雙向鏈表:雙向鏈表也叫雙鏈表,是鏈表的一種,它的每個數據結點中都有兩個指針,分別指向直接后繼和直接前驅。所以,從雙向鏈表中的任意一個結點開始,都可以很方便地訪問它的前驅結點和后繼結點。一般我們都構造雙向循環鏈表。(兩個指針就是一個指向下一個數據,另一個指針指向上一個數據。如圖中head頭指針和tail尾指針)

在這里插入圖片描述
在雙向鏈表中還有一個特殊點,就是頭指針,雙向鏈表是帶頭的。在上次我們說的單鏈表中是不帶頭的,一旦涉及到頭,我們就是先判斷是不是為空,而在雙向鏈表中就是不會涉及到這個問題了,不用再去一個一個的判斷,就會省去很多的麻煩。

帶頭的雙向鏈表嘴尾常用,所以我們這里就介紹帶頭的雙向鏈表

🍌雙向鏈表增刪查改(有頭+雙向+循環鏈表增刪查改實現)

🍍其它接口

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>typedef int LTdatetype;typedef struct ListNode
{LTdatetype date;struct ListNode* next;struct ListNode* tail;
}ListNode;

定義一些接口

🍍創建返回鏈表的頭結點

//創建返回鏈表的頭結點
ListNode* Create(LTdatetype x)
{ListNode* cur =(ListNode*)malloc(sizeof(ListNode));if (cur == NULL){perror("malloc  faild");exit(-1);}cur->next = NULL;cur->tail = NULL;cur->date = x;return cur;
}ListNode* Inia()
{ListNode* node = Create(0);node->next = node;node->tail = node;return node;
}

Create函數就是創建一個節點。而Inia函數本來是進行初始化,而想要變成循環的鏈表,形參改變實參那就要用到二級指針,因為這里是雙向鏈表,涉及頭指針的時候不需要考慮二級指針,所以在這里就只有初始化需要用到頭指針,所以我們就干脆用返回值,這樣就不看起來違和了,當然用二級指針也沒有什么問題,看自己習慣即可。

🍍雙向鏈表銷毀

// 雙向鏈表銷毀
void Destreoy(ListNode* ps)
{assert(ps);ListNode* cur = ps->next;while (cur != ps){cur = cur->next;free(cur->tail);}free(ps);
}

🍍雙向鏈表打印

// 雙向鏈表打印
void Print(ListNode* ps)
{assert(ps);ListNode* cur = ps->next;while (cur != ps){printf("%d<=>", cur->date);cur = cur->next;}
}

在這里插入圖片描述

在這里打印,我們就不能使用和單鏈表打印的方法了,因為我們這里是循環鏈表,并且我們的ps里面沒有存有數據,所以我們要從ps的下個數據開始,也就是圖中cur的位置,然后在cur到ps的時候跳出循環就可以了。

🍍雙向鏈表尾插

// 雙向鏈表尾插
void LTpushbake(ListNode* ps, LTdatetype x)
{assert(ps);ListNode* cur = Create(x);ListNode *node = ps->tail ;//ps的頭要指向curnode->next = cur;//cur的尾要指向pscur->tail = node;//ps的尾要指向curps->tail = cur;//cur的頭要指向pscur->next = ps;
}

在這里插入圖片描述

之所以要這樣的指向,是因為這是一個循環的雙向鏈表

🍍雙向鏈表尾刪

// 雙向鏈表尾刪
void LTpopbake(ListNode* ps)
{assert(ps);assert(ps->next != ps);ListNode* cur = ps->tail;ListNode* curtail = cur->tail;free(cur);cur->next = cur->tail = NULL;curtail->next = ps;ps->tail = curtail;}

在這里插入圖片描述
在這里因為這是循環鏈表所以不用遍歷去找尾結點,當然用遍歷也是可以的

🍍雙向鏈表頭插

// 雙向鏈表頭插
void LTpushfront(ListNode* ps, LTdatetype x)
{assert(ps);ListNode* node = Create(x);ListNode* cur = ps->next;ps->next = node;node->tail = ps;node->next = cur;cur->tail = node;}

在這里插入圖片描述
帶頭的鏈表中,頭插是最方便的,不用像不帶頭的單鏈表中一個一個去判斷,大大的節省了我們的時間

🍍雙向鏈表頭刪

// 雙向鏈表頭刪
void LTpopfront(ListNode* ps)
{assert(ps);assert(ps->next != ps);ListNode* node = ps->next;ListNode* node_next = node->next;free(node);ps->next = node_next;node_next->tail = ps;
}

在這里插入圖片描述
帶頭的鏈表中,頭刪也很方便了。

🍍雙向鏈表查找

// 雙向鏈表查找
ListNode * LTfind(ListNode* ps, LTdatetype x)
{assert(ps);ListNode* cur = ps->next;while (cur != ps){if (cur->date == x){return cur;}cur = cur->next;}return NULL;
}

關于這個查找還是要注意下,因為我們這里是循環鏈表,所以要注意記得要設置跳出循環的條件

🍍雙向鏈表在pos的前面進行插入

// 雙向鏈表在pos的前面進行插入
void LTinsert(ListNode *pos, LTdatetype x)
{assert(pos);ListNode* node = Create(x);ListNode* pos_tail = pos->tail;pos_tail->next = node;node->tail = pos_tail;node->next = pos;pos->tail = node;}

在這里插入圖片描述
在pos前插入和頭插,尾插差不多的意思

🍍雙向鏈表刪除pos位置的節點

// 雙向鏈表刪除pos位置的節點
void LTdelete(ListNode* pos)
{assert(pos);ListNode* pos_tail = pos->tail;ListNode* pos_next = pos->next;free(pos);pos_tail->next = pos_next;pos_next->tail = pos_tail;
}

在這里插入圖片描述

刪除pos位置,也差不多和前面意思都差不多

🍌雙向鏈表整體代碼的實現

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>typedef int LTdatetype;//創建返回鏈表的頭結點
typedef struct ListNode
{LTdatetype date;struct ListNode* next;struct ListNode* tail;
}ListNode;ListNode* Create(LTdatetype x)
{ListNode* cur = (ListNode*)malloc(sizeof(ListNode));if (cur == NULL){perror("malloc  faild");exit(-1);}cur->next = NULL;cur->tail = NULL;cur->date = x;return cur;
}ListNode* Inia()
{ListNode* node = Create(0);node->next = node;node->tail = node;return node;
}// 雙向鏈表銷毀
void Destreoy(ListNode* ps)
{assert(ps);ListNode* cur = ps->next;while (cur != ps){cur = cur->next;free(cur->tail);}free(ps);
}// 雙向鏈表打印
void LTprint(ListNode* ps)
{assert(ps);ListNode* cur = ps->next;printf("ps<=>");while (cur != ps){printf("%d<=>", cur->date);cur = cur->next;}printf("\n");
}// 雙向鏈表尾插
void LTpushbake(ListNode* ps, LTdatetype x)
{assert(ps);ListNode* cur = Create(x);ListNode* node = ps->tail;node->next = cur;cur->tail = node;ps->tail = cur;cur->next = ps;
}// 雙向鏈表尾刪
void LTpopbake(ListNode* ps)
{assert(ps);assert(ps->next != ps);ListNode* cur = ps->tail;ListNode* curtail = cur->tail;free(cur);curtail->next = ps;ps->tail = curtail;}// 雙向鏈表頭插
void LTpushfront(ListNode* ps, LTdatetype x)
{assert(ps);ListNode* node = Create(x);ListNode* cur = ps->next;ps->next = node;node->tail = ps;node->next = cur;cur->tail = node;}// 雙向鏈表頭刪
void LTpopfront(ListNode* ps)
{assert(ps);assert(ps->next != ps);ListNode* node = ps->next;ListNode* node_next = node->next;free(node);ps->next = node_next;node_next->tail = ps;
}// 雙向鏈表查找
ListNode * LTfind(ListNode* ps, LTdatetype x)
{assert(ps);ListNode* cur = ps->next;while (cur != ps){if (cur->date == x){return cur;}cur = cur->next;}return NULL;
}// 雙向鏈表在pos的前面進行插入
void LTinsert(ListNode *pos, LTdatetype x)
{assert(pos);ListNode* node = Create(x);ListNode* pos_tail = pos->tail;pos_tail->next = node;node->tail = pos_tail;node->next = pos;pos->tail = node;}// 雙向鏈表刪除pos位置的節點
void LTdelete(ListNode* pos)
{assert(pos);ListNode* pos_tail = pos->tail;ListNode* pos_next = pos->next;free(pos);pos_tail->next = pos_next;pos_next->tail = pos_tail;
}void test1()//測試
{ListNode* ps = Inia();LTpushbake(ps, 1);//尾插LTpushbake(ps, 2);//尾插LTpushbake(ps, 3);//尾插LTpushbake(ps, 4);//尾插LTprint(ps);//打印LTpopbake(ps);//尾刪LTprint(ps);//打印LTpushfront(ps, 10);//頭插LTpushfront(ps, 11);//頭插LTpushfront(ps, 12);//頭插LTpushfront(ps, 13);//頭插LTprint(ps);//打印LTpopfront(ps);//頭刪LTprint(ps);//打印ListNode *pos = LTfind(ps, 11);//雙向鏈表查找if (pos == NULL){printf("沒找到\n");}else{printf("找到了,為:%d\n", pos->date);}LTinsert(pos, 100);// 雙向鏈表在pos的前面進行插入LTprint(ps);//打印LTdelete(pos);//雙向鏈表刪除pos位置的節點LTprint(ps);//打印Destreoy(ps);//雙向鏈表銷毀
}int main()
{test1();//測試return 0;
}

帶頭的雙向鏈表實現起來還是非常簡單的,大家如果對于文章中的某一個點有問題,歡迎私聊我。

請添加圖片描述

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

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

相關文章

程序啟動時訪問了未初始化的類指針引發內存訪問違例導致程序崩潰的問題排查

目錄 1、問題說明 2、使用Windbg動態調試去初步分析 3、使用Windbg詳細分析 4、最后 VC常用功能開發匯總&#xff08;專欄文章列表&#xff0c;歡迎訂閱&#xff0c;持續更新...&#xff09;https://blog.csdn.net/chenlycly/article/details/124272585C軟件異常排查從入門…

20、XSS——XSS跨站腳本

文章目錄 一、XSS漏洞概述1.1 XSS簡介 二、XSS漏洞分類2.1 反射型XSS2.2 存儲型XSS2.3 DOM型XSS 三、XSS payload構造以及變形3.1 XSS payload構造3.2 XSS payload 變形 一、XSS漏洞概述 1.1 XSS簡介 XSS被稱為跨站腳本攻擊&#xff08;Cross-site scripting&#xff09;&…

linux dpdk 介紹

DPDK&#xff08;Data Plane Development Kit&#xff09;是一個由英特爾發起的開源項目&#xff0c;旨在提供一個快速、高性能的數據平面開發工具包&#xff0c;使網絡應用能夠在通用處理器上實現網絡功能虛擬化&#xff08;NFV&#xff09;和軟件定義網絡&#xff08;SDN&…

k8s volumes and data

Overview 傳統上&#xff0c;容器引擎(Container Engine)不提供比容器壽命更長的存儲。由于容器被認為是瞬態(transient)的&#xff0c;這可能會導致數據丟失或復雜的外部存儲選項。Kubernetes卷共享 Pod 生命周期&#xff0c;而不是其中的容器。如果容器終止&#xff0c;數據…

排序的簡單理解(上)

1. 排序的概念及引用 1.1 排序的概念 排序&#xff1a;所謂排序&#xff0c;就是使一串記錄&#xff0c;按照其中的某個或某些關鍵字的大小&#xff0c;遞增或遞減的排列起來的操作&#xff08;按照我們的需求能夠有序的將數據信息排列起來&#xff09;。 穩定性&#xff1a;假…

TeeChart.NET 2023.11.17 Crack

.NET 的 TeeChart 圖表控件提供了一個出色的通用組件套件&#xff0c;可滿足無數的圖表需求&#xff0c;也針對重要的垂直領域&#xff0c;例如金融、科學和統計領域。 數據可視化 數十種完全可定制的交互式圖表類型、地圖和儀表指示器&#xff0c;以及完整的功能集&#xff0c…

醫療設備智慧管理助力醫院提質增效,阿基米德amp;健康界實踐分享

近日&#xff0c;蘇州阿基米德網絡科技有限公司與醫療領域頭部級媒體健康界&#xff0c;聯合舉辦“數智為擎 提質增效——醫學裝備智慧管理創新發展論壇”的直播活動。 直播現場&#xff0c;來自上海交通大學醫學院附屬同仁醫院、中華醫學會航海醫學分會、蘇州阿基米德的專家們…

統信UOS_麒麟KYLINOS上使用命令行配置NTP服務器

原文鏈接&#xff1a;統信UOS/麒麟KYLINOS上使用命令行配置NTP hello&#xff0c;大家好啊&#xff0c;今天我要給大家介紹的是在統信UOS/麒麟KYLINOS操作系統上使用命令行配置NTP&#xff08;Network Time Protocol&#xff09;服務器的方法。在內網環境下&#xff0c;許多企業…

13、C++異常處理

13、c異常處理 拋出異常捕獲異常未拋出異常時的流程拋出異常時的流程捕獲異常匹配順序異常說明異常處理構造函數中的異常析構函數中的異常標準庫異常類 拋出異常 throw 異常對象可以拋出基本類型的對象&#xff0c;如:throw -1;throw "內存分配失敗!";也可以拋出類類…

AVP對縱向控制ESP(Ibooster)的需求規范

目錄 1. 版本記錄... 3 2. 文檔范圍和控制... 4 2.1 目的/范圍... 4 2.2 文檔沖突... 4 2.3 文檔授權... 4 2.4 文檔更改控制... 4 3. 功能概述... 5 4. 系統架構... 6 5. 主要安全目標... 7 5.1 …

FreeSSL申請免費域名證書

本文詳細講解如何申請免費證書&#xff0c;需要先準備好域名&#xff0c;將服務器IP和域名綁定。 1、注冊FreeSSL賬號 網址&#xff1a; https://freessl.org/ 2、申請流程 登錄后首頁輸入域名&#xff0c;然后點擊Create certificate&#xff0c;跳轉到證書申請頁面。 或者…

Pytorch深度強化學習1-6:詳解時序差分強化學習(SARSA、Q-Learning算法)

目錄 0 專欄介紹1 時序差分強化學習2 策略評估原理3 策略改進原理3.1 SARSA算法3.2 Q-Learning算法 0 專欄介紹 本專欄重點介紹強化學習技術的數學原理&#xff0c;并且采用Pytorch框架對常見的強化學習算法、案例進行實現&#xff0c;幫助讀者理解并快速上手開發。同時&#…

老人的數目

給你一個下標從 0 開始的字符串 details 。details 中每個元素都是一位乘客的信息&#xff0c;信息用長度為 15 的字符串表示&#xff0c;表示方式如下&#xff1a; 前十個字符是乘客的手機號碼。接下來的一個字符是乘客的性別。接下來兩個字符是乘客的年齡。最后兩個字符是乘…

QGIS 加載在線XYZ地圖圖層

QGIS 加載在線XYZ地圖圖層 定義并添加必應XYZ圖層 Go to Layer > Add Layer > Add XYZ Layer…Click NewName as BingMaps(as you wish)URL as http://ecn.t3.tiles.virtualearth.net/tiles/a{q}.jpeg?g1click OkSelect XYZ Connections as Bing Maps(Which you creat…

PR自動剪輯視頻工具AI智能剪輯插件AutoPod

推薦一款可以提高剪輯效率&#xff0c;節約時間成本的AI人工智能自動剪輯視頻制作工具pr插件Autopod&#xff0c;輔助你更快地完成視頻內容的編輯工作。 Autopod 插件是一款應用于 Adobe Premiere Pro 軟件的插件&#xff0c;用于自動剪輯。該插件能夠識別和處理視頻和音頻素材…

Spring Boot 常用注解分類

目錄 1.核心注解&#xff1a;2.配置相關注解&#xff1a;3.控制器相關注解&#xff1a;4.數據訪問相關注解&#xff1a;5.測試相關注解&#xff1a;6.條件注解&#xff1a;7.AOP相關注解&#xff1a;8.定時任務相關注解&#xff1a;9.消息隊列相關注解&#xff1a;10.Spring Se…

函數式編程解析:定義、功能與Java實踐

目錄 一、函數式編程1.1 什么是函數式編程1.2 函數式編程特征1.2.1 純函數1.2.2 函數是一等公民 1.3 函數式編程在java中的實踐 參考資料 一、函數式編程 1.1 什么是函數式編程 函數式編程&#xff08;Functional Programming&#xff09;是一種編程范式&#xff0c;它將計算…

ES6中的迭代器和set、map集合

什么是迭代器&#xff1f; 一種機制&#xff0c;也是一種接口&#xff0c;為數據結構提供統一訪問接口&#xff0c;依次處理數據據結構成員 只要實現了迭代器接口&#xff0c;就可以使用for...of循環遍歷。 /*** 迭代器是一種機制 是一種接口 只要數據解構實現了接口 就可…

力扣labuladong一刷day36天

力扣labuladong一刷day36天 一、96. 不同的二叉搜索樹 題目鏈接&#xff1a;https://leetcode.cn/problems/unique-binary-search-trees/ 思路&#xff1a;這是一道典型的動態規劃題&#xff0c;從n3來看 子樹有幾種形態 (0, 2)、(1, 1)、(2, 0)有規律可循&#xff0c;即為左…

飛天使-linux操作的一些技巧與知識點4

文章目錄 ansible配置文件的優先級嘗試開始進行操作ansible常用模塊ansible 的playbook示例安裝phpplaybook中變量的引用 ansible yum install -y ansible 測試是否可用 ansible localhost -m ping /etc/ansible/ansible.cfg &#xff1a;主配置文件&#xff0c;配置 ansible…