數據結構之鏈表

文章來源:http://blog.seclibs.com/%E6%9...算法

前面講了數據結構中最經常使用、最基礎的數組,接下來講一說數據結構中另外一個比較基礎比較經常使用的數據結構——鏈表,相比於數組來講,鏈表更爲複雜一點,在理解和實現上都比較困難。segmentfault

首先數組必須是一段連續的內存空間來進行存儲的,即便剩餘的內存碎片整合在一塊兒大於所須要的內存也是不能申請成功的,而鏈表則否則,它不須要連續的內存空間,而是靠「指針」將不連續的內存空間都鏈接到一塊兒,若是數組儲存一個數據須要一個空間,那單鏈表就須要兩個,注意是單鏈表,一個用來存數據,一個用來存下一塊內存空間的地址,具體表現以下圖所示數組

上面說數組和鏈表所佔空間的大小的時候,專門說了是單鏈表,由於咱們經常使用的鏈表形式有單鏈表、雙向鏈表和循環鏈表等,單鏈表是其中最簡單、最多見的一個。數據結構

以下圖就是單鏈表的結構圖,每一塊咱們都將它稱爲一個結點,在須要說明當前結點的後一個結點時,咱們常稱爲當前結點的後繼結點,其中date區域是用來存放數據的,next區域是存放指針指向下一塊內存空間的,咱們將它稱爲後繼指針next。學習

在圖中能夠看出來,第一個和最後一個結點是比較特殊的,第一個結點也叫作頭結點,它存儲的是整個鏈表的首地址,也叫作基地址,有了首地址,咱們就能夠遍歷出來整個鏈表中全部的元素;最後一個結點也叫作尾結點,它是沒有後繼結點的,因此它的後繼指針next存放的是NULL,用來表示鏈表已經結束了。spa

與數組同樣,鏈表也支持查找、插入和刪除操做。可是鏈表進行插入和刪除操做是很是的高效的,對於數組來講,它須要有連續的內存空間,因此每次插入和刪除都須要大量的數據移動操做,而鏈表自己就不須要連續的內存空間,因此插入和刪除的時候,只須要更改next的指向,就能夠完成插入和刪除操做了,它所對應的時間複雜度爲O(1)。指針

可是有利就有弊,數組由於內存空間連續,因此支持隨機訪問,知道首地址、數據長度和索引,即可以計算出內存地址,可是在插入和刪除的時候就會有大量的數據移動操做;鏈表偏偏相反,由於內存空間不連續,因此在插入和刪除的時候,只須要更改後繼指針next就能夠了,可是在須要訪問指定位置的數據內容時,就須要從頭結點開始遍歷,一直到所須要查詢的結點爲止,其時間複雜度爲O(n)。blog

接下來咱們來看循環鏈表和雙向鏈表。索引

循環鏈表是特殊的單鏈表,單鏈表的尾結點是指向空地址NULL的,循環鏈表的尾節點指向了頭結點。內存

與單鏈表相比,它更適合從尾結點走到頭結點,對於一些環形結構的數據,循環鏈表就更加適合。

接下來講雙向鏈表,雙向鏈表是更加經常使用的一個鏈表結構,與單鏈表相比,它的date數據區域有先後兩個指針,前驅指針prev和後繼指針next,那麼它儲存一個數據所佔用的空間就更大了,仍是用開頭的那個例子,加入數組佔一個空間,那單鏈表就佔用兩個空間,雙向鏈表就須要佔用三個空間。

雖然它佔用了更多的空間,可是它也比前面的兩個類型更加的靈活,雙向鏈表在處理查詢、插入和刪除操做的時候,與單鏈表相似,可是在一些狀況下,它比單鏈表更加的高效。

假如,咱們要刪除指定指針所指向的結點,在這個狀況下,咱們要刪除結點的時候,首先須要知道刪除結點的前驅結點,而後將前驅結點的後繼指針指向刪除結點的後繼結點。由於單鏈表不能直接獲取到當前結點的前驅結點,因此須要從頭開始遍歷,直到某一結點的next指向了刪除結點,就代表那一個結點爲刪除結點的前驅結點,其時間複雜度爲O(n)。而對於雙向鏈表來講,即可以直接獲取到刪除結點的前驅結點,時間複雜度爲O(1)。一樣在指定結點前插入某個節點,雙向鏈表也同樣更加具備優點。

再假如,若是要查找的鏈表是一個有序鏈表,那麼使用雙向鏈表即可以很是輕鬆的使用二分法來進行查找。

參考文檔
極客時間-數據結構與算法之美

文章首發公衆號和我的博客:

公衆號:無意的夢囈(wuxinmengyi)

這是一個記錄紅隊學習、信安筆記,我的成長的公衆號

掃碼關注便可

博客:http://blog.seclibs.com/

記錄紅隊相關學習筆記

相關文章
相關標籤/搜索