自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

雙鏈表,這回徹底搞dong了

開(kāi)發(fā) 前端
前面有很詳細(xì)的講過(guò)線(xiàn)性表(順序表和鏈表),當(dāng)時(shí)講的鏈表以單鏈表為主,但實(shí)際上在實(shí)際應(yīng)用中雙鏈表的應(yīng)用多一些就比如LinkedList。

前言

前面有很詳細(xì)的講過(guò)線(xiàn)性表(順序表和鏈表),當(dāng)時(shí)講的鏈表以單鏈表為主,但實(shí)際上在實(shí)際應(yīng)用中雙鏈表的應(yīng)用多一些就比如LinkedList。

[[387782]]

雙鏈表與單鏈表區(qū)別

邏輯上它們均是線(xiàn)性表的鏈?zhǔn)綄?shí)現(xiàn),主要的區(qū)別是節(jié)點(diǎn)結(jié)構(gòu)上的構(gòu)造有所區(qū)別,這個(gè)區(qū)別從而引起操作的一些差異。

單鏈表

單鏈表的一個(gè)節(jié)點(diǎn),有儲(chǔ)存數(shù)據(jù)的data,還有后驅(qū)節(jié)點(diǎn)next(指針)。也就是這個(gè)單鏈表想要一些遍歷的操作都得通過(guò)前節(jié)點(diǎn)—>后節(jié)點(diǎn)。

 

雙鏈表:

雙鏈表的一個(gè)節(jié)點(diǎn),有存儲(chǔ)數(shù)據(jù)的data,也有后驅(qū)節(jié)點(diǎn)next(指針),這和單鏈表是一樣的,但它還有一個(gè)前驅(qū)節(jié)點(diǎn)pre(指針)。


雙鏈表結(jié)構(gòu)的設(shè)計(jì)

上文講單鏈表的時(shí)候,我們當(dāng)時(shí)設(shè)計(jì)的是一個(gè)帶頭結(jié)點(diǎn)的鏈表就錯(cuò)過(guò)了不帶頭結(jié)點(diǎn)操作方式,這里雙鏈表咱們就不帶頭結(jié)點(diǎn)設(shè)計(jì)實(shí)現(xiàn)。并且上文單鏈表實(shí)現(xiàn)的時(shí)候是沒(méi)有尾指針tail的,在這里我們?cè)O(shè)計(jì)的雙鏈表帶尾指針

所以我們構(gòu)造的這個(gè)雙鏈表是:不帶頭節(jié)點(diǎn)、帶尾指針(tail)、雙向鏈表

對(duì)于node節(jié)點(diǎn):

  1. class node<T> { 
  2.   T data; 
  3.     node<T> pre; 
  4.     node<T> next
  5.  
  6.     public node() { 
  7.     } 
  8.  
  9.     public node(T data) { 
  10.         this.data = data; 
  11.     } 

對(duì)于鏈表:

  1. public class doubleList<T> { 
  2.   private node<T> head;// 頭節(jié)點(diǎn) 
  3.     private node<T> tail;// 尾節(jié)點(diǎn) 
  4.     private int length; 
  5.     //各種方法     

具體操作分析

對(duì)于一個(gè)鏈表主要的操作還是增刪。增刪的話(huà)不光需要考慮鏈表是否帶頭節(jié)點(diǎn),還有頭插、尾插、中間插等多種插入刪除形式,其中的一些細(xì)節(jié)處理也是比較重要的(防止鏈表崩掉出錯(cuò)),如果你對(duì)這塊理解不夠深入很容易寫(xiě)錯(cuò)也很難排查出來(lái)。當(dāng)然,鏈表的查找、按位修改操作相比增刪操作還是容易很多。

初始化

雙鏈表在最初的時(shí)候頭指針指向?yàn)閚ull。那么對(duì)于這個(gè)不帶頭節(jié)點(diǎn)的雙鏈表而言。它的head始終指向第一個(gè)真實(shí)有效的節(jié)點(diǎn)。tail也指向最后一個(gè)有效的節(jié)點(diǎn)。在最初的時(shí)候head=null,并且tail=head,此時(shí)鏈表為空,等待節(jié)點(diǎn)插入。

  1. public doubleList() { 
  2.     head = null
  3.     tail = head; 
  4.     length = 0; 
  5.     } 

插入

空鏈表插入

對(duì)于空鏈表來(lái)說(shuō)。增加第一個(gè)元素可以特殊考慮。因?yàn)樵阪湵頌榭盏臅r(shí)候head和tail均為null。但head和tail又需要實(shí)實(shí)在在指向鏈表中的真實(shí)數(shù)據(jù)(帶頭指針就不需要考慮)。所以這時(shí)候就新建一個(gè)node讓head、tail等于它。

  1. node<T> teamNode = new node(data); 
  2. if (isEmpty()) { 
  3.     head = teamNode; 
  4.     tail = teamNode;     

頭插

對(duì)于頭插入來(lái)說(shuō)。步驟很簡(jiǎn)單,只需考慮head節(jié)點(diǎn)的變化。

  1. 新建插入節(jié)點(diǎn)node
  2. head前驅(qū)指向node
  3. node后驅(qū)指向head
  4. head指向node。(這時(shí)候head只是表示第二個(gè)節(jié)點(diǎn),而head需要表示第一個(gè)節(jié)點(diǎn)故改變指向)
圖片

尾插:

對(duì)于尾插入來(lái)說(shuō)。只需考慮尾節(jié)點(diǎn)tail節(jié)點(diǎn)的變化。

  1. 新建插入節(jié)點(diǎn)node
  2. node前驅(qū)指向tail
  3. tail后驅(qū)指向node
  4. tail指向node。(這時(shí)候tail只是表示倒數(shù)第二個(gè)節(jié)點(diǎn),而tail需要表示最后節(jié)點(diǎn)故指向node)
圖片

按編號(hào)插入

對(duì)于編號(hào)插入來(lái)說(shuō)。要考慮查找和插入兩步,而插入既和head無(wú)關(guān)也和tail無(wú)關(guān)。

1 新建插入節(jié)點(diǎn)node

2 找到欲插入node的前一個(gè)節(jié)點(diǎn)preNode。和后一個(gè)節(jié)點(diǎn)nextNode

3 node后驅(qū)指向nextNode,nextNode前驅(qū)指向node(此時(shí)node和后面與鏈表已經(jīng)聯(lián)立,但是和前面處理分離狀態(tài))

4 preNode后驅(qū)指向node。node前驅(qū)指向preNode(此時(shí)插入完整操作完畢)


整個(gè)流程的動(dòng)態(tài)圖為:

圖片

刪除

只有單個(gè)節(jié)點(diǎn)刪除

無(wú)論頭刪還是尾刪,遇到單節(jié)點(diǎn)刪除的需要將鏈表從新初始化!

  1. if (length == 1)// 只有一個(gè)元素 
  2.     head = null
  3.     tail = head; 
  4.     length--; 

頭刪除

頭刪除需要注意的就是刪除不為空時(shí)候頭刪除只和head節(jié)點(diǎn)有關(guān)

流程大致分為:

1 head節(jié)點(diǎn)的后驅(qū)節(jié)點(diǎn)的前指針pre改為null。(head后面節(jié)點(diǎn)本指向head但是要?jiǎng)h除第一個(gè)先讓后面那個(gè)和head斷絕關(guān)系)


2 head節(jié)點(diǎn)指向head.next(這樣head就指向我們需要的第一個(gè)節(jié)點(diǎn)了,前面節(jié)點(diǎn)就被刪除成功,如果有c++等語(yǔ)言第一個(gè)被孤立的節(jié)點(diǎn)刪除釋放即可,但Java會(huì)自動(dòng)釋放)


尾刪除

尾刪除需要注意的就是刪除不為空時(shí)候尾刪除只和tail節(jié)點(diǎn)有關(guān)。記得在普通鏈表中,我們刪除尾節(jié)點(diǎn)需要找到尾節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn)。需要遍歷整個(gè)表,而雙向鏈表可以直接從尾節(jié)點(diǎn)遍歷到前面。

尾刪除就是刪除雙向鏈表中的最后一個(gè)節(jié)點(diǎn),也就是尾指針?biāo)赶虻哪莻€(gè)節(jié)點(diǎn),思想和頭刪除的思想一致,具體步驟為:

  1. tail.pre.next=null尾節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)(pre)的后驅(qū)節(jié)點(diǎn)等于null
  2. tail=tail.pre尾節(jié)點(diǎn)指向它的前驅(qū)節(jié)點(diǎn),此時(shí)尾節(jié)點(diǎn)由于步驟1next已經(jīng)為null。完成刪除
圖片

普通刪除

普通刪除需要重點(diǎn)掌握,普通刪除要妥善處理好待刪除節(jié)點(diǎn)的前后關(guān)系,具體流程如下:

1:找到待刪除節(jié)點(diǎn)node的前驅(qū)節(jié)點(diǎn)prenode(prenode.next是要?jiǎng)h除的節(jié)點(diǎn))

2 : prenode.next.next.pre=prenode.(將待刪除node的后驅(qū)節(jié)點(diǎn)aftnode的pre指針指向prenode,等價(jià)于aftnode.pre=prenode)

 

3: prenode.next=prenode.next.next;此時(shí)node被跳過(guò)成功刪除。


完成刪除整個(gè)流程的動(dòng)態(tài)圖為:

圖片

實(shí)現(xiàn)與測(cè)試

通過(guò)上面的思路簡(jiǎn)單的實(shí)現(xiàn)一下雙鏈表,當(dāng)然有些地方命名不太規(guī)范,實(shí)現(xiàn)效率有待提升,主要目的還是帶著大家理解。

代碼(代碼以圖片方式貼出,如需源碼可閱讀原文或者加我好友發(fā)你):


 

測(cè)試:


結(jié)語(yǔ)

在插入刪除的步驟,很多人可能因?yàn)榉爆嵉倪^(guò)程而弄不明白,但實(shí)際上這個(gè)操作的寫(xiě)法可能是多樣的,但本質(zhì)操作都是一致的,所以看到其他不同版本有差距也是正常的。

還有很多人可能對(duì)一堆next.next搞不清楚,那我教你一個(gè)技巧,如果在等號(hào)右側(cè),那么它表示一個(gè)節(jié)點(diǎn),如果在等號(hào)左側(cè),那么除了最后一個(gè).next其他的表示節(jié)點(diǎn)。例如node.next.next.next可以看成(node.next.next).next。

在做數(shù)據(jù)結(jié)構(gòu)與算法鏈表相關(guān)題的時(shí)候,不同題可能給不同節(jié)點(diǎn)去完成插入、刪除操作。這種情況操作時(shí)候要謹(jǐn)慎先后順序防止破壞鏈表結(jié)構(gòu)。

代碼操作可能有些優(yōu)化空間,還請(qǐng)各位大佬指正!如有收獲

 

 

責(zé)任編輯:姜華 來(lái)源: bigsai
相關(guān)推薦

2023-12-28 10:39:57

數(shù)組節(jié)點(diǎn)數(shù)據(jù)結(jié)構(gòu)

2024-05-09 09:09:19

組合模式對(duì)象

2024-05-10 08:43:04

外觀(guān)模式接口系統(tǒng)

2024-05-13 10:45:25

中介模式面向?qū)ο?/a>數(shù)量

2019-08-27 14:46:59

ElasticSearES數(shù)據(jù)庫(kù)

2022-04-10 18:10:24

CURD鏈表

2023-02-27 08:10:16

2023-11-08 07:56:38

單鏈表雙鏈表

2024-05-15 10:14:00

CRDT數(shù)據(jù)類(lèi)型協(xié)同編輯

2024-05-11 14:18:44

迭代器模式業(yè)務(wù)

2024-03-11 08:47:30

CRDT數(shù)據(jù)類(lèi)型協(xié)同編輯

2024-05-17 10:08:59

享元模式分類(lèi)方式

2021-12-14 15:43:16

機(jī)器學(xué)習(xí)人工智能代碼

2021-09-23 16:50:19

芯片摩根士丹利半導(dǎo)體

2021-08-02 08:26:00

技術(shù)員工P7

2022-04-12 07:51:31

架構(gòu)TPSQPS

2024-05-15 17:41:37

備忘錄模式多線(xiàn)程

2021-07-15 06:43:12

Python數(shù)據(jù)結(jié)構(gòu)

2021-11-26 07:45:37

編碼GBK字符

2018-03-08 13:20:30

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)