數(shù)據(jù)結(jié)構(gòu)之「鏈表」

什么是鏈表粟誓?

鏈表是一種線性表枷邪,但并不會按線性的順序存儲數(shù)據(jù)隙畜,而是在每一個(gè)節(jié)點(diǎn)里存儲到下一個(gè)節(jié)點(diǎn)的指針 (Pointer)抖部。因此它不需要分配連續(xù)的存儲空間,也不需要預(yù)先固定元素的大小议惰,它可以動(dòng)態(tài)的添加和刪除元素慎颗,而且時(shí)間復(fù)雜度是 O(1)。只不過查找某個(gè)元素時(shí)言询,時(shí)間復(fù)雜度是 O(n)俯萎。
鏈表有多種不同的類型:單向鏈表,雙向鏈表和循環(huán)鏈表运杭。

單向鏈表

單向鏈表是最簡單的一種夫啊,它包含兩個(gè)域,一個(gè)信息域和一個(gè)指針域辆憔。這個(gè)指針域指向列表中的下一個(gè)節(jié)點(diǎn)撇眯,而最后一個(gè)節(jié)點(diǎn)則指向一個(gè)空值。


單向鏈表
雙向鏈表

雙向鏈表中不僅有指向后一個(gè)節(jié)點(diǎn)的指針躁愿,還有指向前一個(gè)節(jié)點(diǎn)的指針叛本。這樣可以從任何一個(gè)節(jié)點(diǎn)訪問前一個(gè)節(jié)點(diǎn)沪蓬,當(dāng)然也可以訪問后一個(gè)節(jié)點(diǎn)彤钟。

雙向鏈表
循環(huán)鏈表

循環(huán)鏈表是把鏈表的首節(jié)點(diǎn)和末節(jié)點(diǎn)連接在一起,形成一個(gè)環(huán)跷叉。這種方式在單向和雙向鏈表中皆可實(shí)現(xiàn)逸雹。

循環(huán)鏈表

鏈表有什么作用?

根據(jù)鏈表的特性云挟,動(dòng)態(tài)的把元素加入到鏈表中梆砸,不需要預(yù)先指定鏈表長度,理論上鏈表可以無限長园欣,直到內(nèi)存耗盡帖世。鏈表會存儲下一個(gè)元素的地址,因此插入和刪除會很方便沸枯,但查詢指定元素時(shí)日矫,最壞的情況是遍歷整個(gè)鏈表。

鏈表該怎么使用绑榴?

這里我用 Java 語言來簡單實(shí)現(xiàn)鏈表哪轿,可參考 JDK 的 LinkedList。
構(gòu)建鏈表結(jié)構(gòu)

//創(chuàng)建一個(gè)私有的靜態(tài)的Node泛型對象
public class LinkedList<E> {
Node<E> first;//第一個(gè)節(jié)點(diǎn)
Node<E> last;//最后一個(gè)節(jié)點(diǎn)
private static class Node<E> {
    E item;//存儲元素
    Node<E> next;//下一個(gè)元素
    Node<E> prev;//上一個(gè)元素
    //通過構(gòu)造器設(shè)置值
    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}

在鏈表后插入元素翔怎,前面插入也類似

//中間變量存儲鏈表的最后一個(gè)節(jié)點(diǎn)
Node<E> l = last;
//構(gòu)建新節(jié)點(diǎn)窃诉,頭節(jié)點(diǎn)指向鏈表的最后節(jié)點(diǎn)
Node<E> newNode = new Node<>(l, 5, null);
//把新節(jié)點(diǎn)當(dāng)作最后一個(gè)節(jié)點(diǎn)
last = newNode;
//if 最后節(jié)點(diǎn)為空杨耙,說明是一個(gè)新鏈表
if (l == null)
    first = newNode;
//否則把鏈表最后一個(gè)節(jié)點(diǎn)的 next 節(jié)點(diǎn)指向新節(jié)點(diǎn)
else
    l.next = newNode;

刪除指定節(jié)點(diǎn) d

E element = d.item;
Node<E> next = d.next;
Node<E> prev = d.prev;
//if 當(dāng)前節(jié)點(diǎn)的上一個(gè)節(jié)點(diǎn)為空,
//說明刪除的是第一個(gè)節(jié)點(diǎn)飘痛,
//把當(dāng)前節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)置為第一個(gè)節(jié)點(diǎn)珊膜。
if (prev == null) {
    first = next;
//否則把上一個(gè)節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)指向當(dāng)前節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn),
//相當(dāng)于跳過了當(dāng)前節(jié)點(diǎn)宣脉,并把當(dāng)前節(jié)點(diǎn)的上一個(gè)節(jié)點(diǎn)置空辅搬。
} else {
    prev.next = next;
    d.prev = null;
}
//if 當(dāng)前節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)為空,說明是最后一個(gè)節(jié)點(diǎn)脖旱。
//把最后一個(gè)節(jié)點(diǎn)置為上一個(gè)節(jié)點(diǎn)堪遂。
if (next == null) {
    last = prev;
//否則把當(dāng)前的上一節(jié)點(diǎn)指向當(dāng)前的下一個(gè)節(jié)點(diǎn),
//相當(dāng)于跳過當(dāng)前節(jié)點(diǎn)萌庆,在把當(dāng)前節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)置空溶褪。
} else {
    next.prev = prev;
    d.next = null;
}
//置空當(dāng)前節(jié)點(diǎn)元素,幫助 GC 回收
d.item = null;

遍歷鏈表

Node<E> d = first;
while (d != null && d.next != null) {
    System.out.println(d.item);
    d = d.next;
}

總結(jié)

數(shù)組需要初始化確定好長度践险,并且不能修改數(shù)組的長度猿妈。在有的場景下,是不知道有多少元素的巍虫,因此我們是不能準(zhǔn)確的分配數(shù)組的長度彭则。但也提供了數(shù)組擴(kuò)容的方案,就是在現(xiàn)有的數(shù)組大小上占遥,在按一定算法來創(chuàng)建一個(gè)新的數(shù)組俯抖,并把數(shù)組的數(shù)據(jù)拷貝進(jìn)擴(kuò)容后的數(shù)組里去,但數(shù)組的擴(kuò)容是很影響性能的瓦胎。因此需要一種新的數(shù)據(jù)結(jié)構(gòu)來存儲不能確定有多少元素的數(shù)據(jù)芬萍,這就是鏈表的應(yīng)用場景。
但它也有缺點(diǎn)搔啊,每個(gè)節(jié)點(diǎn)多需要多的空間來存儲下一個(gè)節(jié)點(diǎn)的地址柬祠,查詢時(shí)最壞情況是遍歷整個(gè)數(shù)組。
它的優(yōu)點(diǎn)是不需要預(yù)分配固定大小负芋,不限制元素個(gè)數(shù)漫蛔,理論上可以直到內(nèi)存耗盡,插入和刪除時(shí)間復(fù)雜度是 O(1)旧蛾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末莽龟,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蚜点,更是在濱河造成了極大的恐慌轧房,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绍绘,死亡現(xiàn)場離奇詭異奶镶,居然都是意外死亡迟赃,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門厂镇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來纤壁,“玉大人,你說我怎么就攤上這事捺信∽妹剑” “怎么了?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵迄靠,是天一觀的道長秒咨。 經(jīng)常有香客問我,道長掌挚,這世上最難降的妖魔是什么雨席? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮吠式,結(jié)果婚禮上陡厘,老公的妹妹穿的比我還像新娘。我一直安慰自己特占,他們只是感情好糙置,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著是目,像睡著了一般谤饭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胖笛,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天网持,我揣著相機(jī)與錄音宜岛,去河邊找鬼长踊。 笑死,一個(gè)胖子當(dāng)著我的面吹牛萍倡,可吹牛的內(nèi)容都是我干的身弊。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼列敲,長吁一口氣:“原來是場噩夢啊……” “哼阱佛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起戴而,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤凑术,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后所意,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體淮逊,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡催首,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了泄鹏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片郎任。...
    茶點(diǎn)故事閱讀 40,680評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖备籽,靈堂內(nèi)的尸體忽然破棺而出舶治,到底是詐尸還是另有隱情,我是刑警寧澤车猬,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布霉猛,位于F島的核電站,受9級特大地震影響珠闰,放射性物質(zhì)發(fā)生泄漏韩脏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一铸磅、第九天 我趴在偏房一處隱蔽的房頂上張望赡矢。 院中可真熱鬧,春花似錦阅仔、人聲如沸吹散。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽空民。三九已至,卻和暖如春羞迷,著一層夾襖步出監(jiān)牢的瞬間界轩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工衔瓮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留浊猾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓热鞍,卻偏偏與公主長得像葫慎,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子薇宠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 強(qiáng)掰成左手澄港。 初中習(xí)慣了椒涯,時(shí)不時(shí)左手運(yùn)球;還記得初三有一個(gè)月持續(xù)用左手使筷子吃粉回梧;高中刻意學(xué)AI的cros...
    EnriqueCruz閱讀 214評論 0 0
  • 夏天到啦废岂,小伙伴備受蚊子侵?jǐn)_铡溪,一小和尚說他去想辦法 小和尚來問方丈,出家人最要緊的是什么泪喊,方丈說要心存善念 那別人...
    泥后陶閱讀 384評論 0 0
  • 第一次讀《JavaScript高級程序設(shè)計(jì)(第三版)》棕硫,沒怎么注意和理解JavaScript 動(dòng)態(tài)集合的概念,最近...
    貴在隨心閱讀 957評論 0 5