網站首頁 編程語言 正文
前言
鏈表(linked list)是一種這樣的數據結構,其中的各對象按線性排列。數組的線性順序是由數組下標決定的,然而于數組不同的是,鏈表的各順序是由鏈表中的指針決定的。
雙向鏈表也叫雙鏈表,是鏈表的一種,它的每個數據結點中都有兩個指針,分別指向直接后繼和直接前驅。所以,從雙向鏈表中的任意一個結點開始,都可以很方便地訪問它的前驅結點和后繼結點。一般我們都構造雙向循環鏈表。
雙向鏈表的定義
雙鏈表(doubly linked list)的每一個元素都是一個對象,每一個對象都有一個數據域和兩個指針front和tail。對象中還可以包含其他輔助數據。設L為鏈表的一個元素,L.front指向他在鏈表中的后繼元素,L.tail指向他的前繼元素。
我們可以定義一個結構體封裝這些數據
typedef struct Node { int data; struct Node* front; struct Node* tail; }NODE, * LPNODE;
雙向鏈表的創建
在C++中,我們以類的形式封裝了雙向鏈表。在類中,我們定義了兩個指針,一個是指向鏈表的頭部?frontNode,一個是指向了鏈表的尾部?tailNode,另外我們還加入了?curSize屬性,記錄節點的個數。在對象創建的過程就是鏈表創建的過程,我們只需要在類的構造函數中初始化參數即可。
class duplexHead { public: duplexHead() { frontNode = NULL; tailNode = NULL; curSize = 0; } LPNODE createNode(int data); LPNODE seachNode(int data); void push_front(int data); void push_back(int data); void push_appoin(int posData, int data); void pop_front(); void pop_back(); void pop_appoin(int posData); void printByFront(); void printByTail(); protected: LPNODE frontNode; LPNODE tailNode; int curSize; };
節點的創建
在上面,我們已經知道雙向鏈表的單體長啥樣了,我們只需要給他的單體分配空間然后初始化他的參數即可。
LPNODE duplexHead::createNode(int data) { LPNODE newNode = new NODE; assert(newNode); newNode->front = nullptr; newNode->tail = nullptr; newNode->data = data; return newNode; }
雙向鏈表節點查找
? ? ?鏈表的查找我們可以定義一個函數LPNODE seachNode(int data),當滿足查找條件時,我們就返回當前節點的鏈表。在實際操作過程中,鏈表的數據域可能會有多個數據,可能要比較int 類型,可能要比較string類型等多種變化,這是我們可以在參數列表預留一個函數指針 (int)? (*comparData)(LPNODE? data),以應對多種需求。當然,在這里為了演示方便,我們就用一個int 類型的數據代替了。
LPNODE duplexHead::seachNode(int data) { if (!curSize) { printf("鏈表為空,無法查找"); return; } LPNODE preNode = frontNode; LPNODE curNode = frontNode; while (curNode != NULL && curNode->data != data) { preNode = curNode; curNode = preNode->tail; } if (curNode == nullptr) { printf("鏈表中沒有該數據"); return nullptr; } return curNode; }
雙向鏈表的插入
插入節點,我們分為頭部插入和尾部插入以及指定位置插入。而這三種插入,都可分為3步。
(1)創建新節點
(2)找到插入位置
(3)插入
我們就以制定位置插入為例,如圖所示,我們只需把原來相連的兩個節點斷開,然后再分別用指針拼接起來,當然我們也可以調用我們的seachNode來查找位置,這樣就更方便一些了。
void duplexHead::push_appoin(int posData, int data) { if (curSize == 0) return; if (frontNode->data == posData) { push_front(data); } else { LPNODE preNode = frontNode; LPNODE curNode = frontNode; while (curNode != NULL && curNode->data != posData) { preNode = curNode; curNode = preNode->tail; } if (curNode == NULL) { printf("未找到指定位置,無法插入!\n"); } else { LPNODE newNode = createNode(data); preNode->tail = newNode; newNode->tail = curNode; curNode->front = newNode; newNode->front = preNode; curSize++; } } }
雙向鏈表的節點刪除
刪除節點我們也可以分為頭部刪除,尾部刪除,指定數據刪除。他與插入節點幾乎是一樣的
(1)找到刪除位置
(2)刪除
我們就以指定數據刪除為例,我們通過while或者seachNode來查找到要刪除的節點,然后把他的front 指向的位置和tail指向的位置記住,就可以直接刪除節點了。刪除完了節點要記得把前后段的鏈表連接上即可。
void duplexHead::pop_appoin(int posData) { if (frontNode == NULL || curSize == 0) { printf("鏈表為空無法刪除!"); return; } if (frontNode->data == posData) { pop_front(); return; } LPNODE preNode = frontNode; LPNODE curNode = frontNode; while (curNode != NULL && curNode->data != posData) { preNode = curNode; curNode = preNode->tail; } if (curNode == NULL) { printf("未找到指定位置無法刪除!\n"); } else { if (tailNode == curNode) { pop_back(); } else { preNode->tail = curNode->tail; //curNode->tail是不是不空 //當刪除的表尾時候,curNode->tail等于空 curNode->tail->front = preNode; free(curNode); curNode = NULL; curSize--; } } }
雙向鏈表的刪除
于雙向鏈表的創建一樣,我們可以把雙向鏈表的刪除放在析構函數中,實現創建和刪除自動化,當對象被創建,雙向鏈表就被創建,當對象消亡,雙向鏈表就刪除了。
duplexHead::~duplexHead() { if (!frontNode)return; LPNODE pmove ; while (!pmove) { pmove = frontNode->tail; delete frontNode->tail; frontNode = pmove; } }
總結
原文鏈接:https://blog.csdn.net/weixin_52079669/article/details/122525114
相關推薦
- 2021-12-12 C++多線程之互斥鎖與死鎖_C 語言
- 2024-01-29 在springboot多數據源項目中創建多個事務(解決@Transactional影響切換數據源問題
- 2022-02-03 gogs倉庫代碼拉取不需要用戶賬號驗證問題
- 2022-09-17 C/C++?控制臺等待指令解析_C 語言
- 2024-03-04 echarts 柱狀圖,單獨一根柱子根據條件改變顏色
- 2022-04-20 python數據類型中的字符串你了解多少_python
- 2023-07-07 Tomcat文件夾屬性
- 2022-04-07 WPF實現數據綁定_實用技巧
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支