03-鏈表(單向鏈表)

在上一節(jié),我們知道了動(dòng)態(tài)數(shù)組實(shí)現(xiàn)的大概原理,不過(guò),動(dòng)態(tài)數(shù)組卻有一個(gè)明顯的缺點(diǎn),即可能會(huì)造成內(nèi)存空間的大量浪費(fèi)。因?yàn)楫?dāng)動(dòng)態(tài)數(shù)組空間使用完以后,會(huì)申請(qǐng)一個(gè)更大的空間,用來(lái)保存數(shù)據(jù),但是更大空間的數(shù)組,卻不一定能全部使用,因此可能造成空間浪費(fèi)。

??能否做到用到多少就申請(qǐng)多少內(nèi)存呢?

有!鏈表就可以做到這一點(diǎn)。

  • 鏈表

鏈表是一種鏈?zhǔn)酱鎯?chǔ)的線性表,所有元素的內(nèi)存地址不一定是連續(xù)的;

例如我們添加一個(gè)元素,會(huì)首先為則個(gè)元素分配存儲(chǔ)空間,并且在鏈表中存儲(chǔ)數(shù)據(jù),會(huì)首先創(chuàng)建出一個(gè)node節(jié)點(diǎn)對(duì)象,其中內(nèi)部會(huì)有一塊存儲(chǔ)空間,用來(lái)保存要存儲(chǔ)的數(shù)據(jù),例如下圖是一個(gè)首節(jié)點(diǎn)
1566305122630.png

假設(shè)有兩個(gè)節(jié)點(diǎn)對(duì)象,則如下圖所示進(jìn)行關(guān)聯(lián)
1566305226539.png

以此類推,當(dāng)有多個(gè)節(jié)點(diǎn)時(shí),會(huì)像下圖一樣相互關(guān)聯(lián)
1566305313016.png

所以,由于每次添加一個(gè)元素,都是新分配的內(nèi)存空間,說(shuō)一每個(gè)節(jié)點(diǎn)之間的內(nèi)存地址并不一定是連續(xù)的。

當(dāng)某個(gè)節(jié)點(diǎn)是尾節(jié)點(diǎn)時(shí),尾節(jié)點(diǎn)的下一個(gè)Node地址將指向null,用圖形表示如下
1566305570732.png
  • 鏈表的設(shè)計(jì)

鏈表中應(yīng)該包含的元素

  1. size - 保持鏈表的大小

  2. first - 指向鏈表的頭節(jié)點(diǎn)

1566305881624.png

一個(gè)完整的鏈表,用圖形表示如下

1566306009091.png

了解了鏈表的設(shè)計(jì)以后,我們就可以來(lái)了解一下鏈表的接口設(shè)計(jì)了。

  • 鏈表的接口設(shè)計(jì)

小提示:在閱讀該小節(jié)時(shí),建議結(jié)合demo源碼進(jìn)行同步閱讀效果更佳,demo源碼地址

由于鏈表和動(dòng)態(tài)數(shù)組都是線性表,因此鏈表的大部分接口和動(dòng)態(tài)數(shù)組是一致的,但實(shí)現(xiàn)方式不一樣。因此我們可以將鏈表和動(dòng)態(tài)數(shù)組的接口統(tǒng)一申明到接口文件中,關(guān)系如下
1566310283422.png

由于在動(dòng)態(tài)數(shù)組與鏈表之間,存在一些接口的實(shí)現(xiàn)和一些相同的方法,因此可以抽取一個(gè)抽象類與一個(gè)接口,來(lái)管理接口與方法的實(shí)現(xiàn),因此有了如下的設(shè)計(jì)
1566310539362.png

至此,鏈表的接口設(shè)計(jì)就完成了,接下來(lái)再來(lái)了解一下接口的實(shí)現(xiàn)

  • 清空鏈表 - clear()

首先,我們假設(shè)現(xiàn)在有一個(gè)結(jié)構(gòu)如下的鏈表對(duì)象
1566310888924.png

我們需要做的事情就是

  1. 將size設(shè)置為0

  2. 將LinkedList對(duì)象中的first字段設(shè)置為null,當(dāng)我們將first設(shè)置為null時(shí),相當(dāng)于頭節(jié)點(diǎn)沒(méi)有引用指向它,頭節(jié)點(diǎn)的內(nèi)存就會(huì)被系統(tǒng)回收,然后后節(jié)點(diǎn)依次被系統(tǒng)銷毀
    1566311205757.png

??這里的next需要設(shè)置為null嗎?

  • 添加節(jié)點(diǎn) - add(int index, E element)

假設(shè)現(xiàn)在有如下的鏈表,需要往Node節(jié)點(diǎn)為1的位置添加一個(gè)值為44新的Node節(jié)點(diǎn)
1566311487936.png

操作步驟如下

  1. 將新節(jié)點(diǎn)的next指向Node為1的節(jié)點(diǎn)
    1566311664168.png
  1. 然后再讓Node為1節(jié)點(diǎn)前面的節(jié)點(diǎn)里面的next指向新的節(jié)點(diǎn)


    1566311737348.png
  2. 最后更新索引,就完成了節(jié)點(diǎn)的添加
    1566311790460.png

不過(guò)需要注意的是,再添加元素時(shí),要特殊處理0的位置
1566312668890.png

因此,編寫(xiě)鏈表的過(guò)程中,要注意邊界測(cè)試,如index = 0、size - 1、size時(shí)

  • 刪除元素 - remove(int index)

    假設(shè)有以下一個(gè)鏈表對(duì)象,其中我們要?jiǎng)h除Node為1的節(jié)點(diǎn)
    1566313216717.png

操作方法非常簡(jiǎn)單,我們只需要將Node為0節(jié)點(diǎn)中的next指向其下下個(gè)節(jié)點(diǎn)即可
1566313330502.png

修改Node為0的next指向后,Node為1的節(jié)點(diǎn)沒(méi)有引用指向他,其內(nèi)存就會(huì)被系統(tǒng)回收掉
1566313429508.png

刪除節(jié)點(diǎn)具體步驟

  1. 找到被刪除節(jié)點(diǎn)的前一個(gè)節(jié)點(diǎn)

  2. 將前一個(gè)節(jié)點(diǎn)中的next賦值為下被刪除節(jié)點(diǎn)的next即可

好工具分享-推薦一個(gè)神奇的網(wǎng)站給大家 數(shù)據(jù)結(jié)構(gòu)和算法動(dòng)態(tài)可視化 ,又興趣的讀者可以去看看,非常推薦

鏈表練習(xí)題 - 題目來(lái)自leetcode

題目1 刪除鏈表中的節(jié)點(diǎn)

題目2 反轉(zhuǎn)一個(gè)鏈表 題目解析

題目3 判斷一個(gè)鏈表是否有環(huán) 題目解析

demo源碼下載地址

本節(jié)完!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容