鏈表(Linked list)是一種線性表,可是並不會在物理存儲上按線性的順序存儲數據,而是在每個節點裏存到下一個節點的指針(Pointer)。因爲沒必要須按順序存儲,鏈表的插入和刪除操做能夠達到O(1)的複雜度。本文將講解單向鏈表和雙向鏈表,其中雙向鏈表會給出部分關鍵代碼實現。node
單向鏈表(單鏈表)是鏈表的一種,它由節點組成,每一個節點都包含下一個節點的指針,下圖就是一個單鏈表,表頭爲空,表頭的後繼節點是"結點10"(數據爲10的結點),"節點10"的後繼結點是"節點20"(數據爲10的結點),...算法
咱們看看單鏈表刪除節點的操做,好比說下面這個單鏈表中咱們要刪除"節點30"。編程
刪除以前:"節點20" 的後繼節點爲"節點30",而"節點30" 的後繼節點爲"節點40"。緩存
刪除以後:"節點20" 的後繼節點爲"節點40"。服務器
咱們再來看看單鏈表添加節點的操做,好比說下面這個單鏈表中咱們在"節點10"與"節點20"之間添加"節點15"數據結構
添加以前:"節點10" 的後繼節點爲"節點20"。併發
添加以後:"節點10" 的後繼節點爲"節點15",而"節點15" 的後繼節點爲"節點20"。ide
雙向鏈表(雙鏈表)是鏈表的一種。和單鏈表同樣,雙鏈表也是由節點組成,它的每一個數據結點中都有兩個指針,分別指向直接後繼和直接前驅。因此,從雙向鏈表中的任意一個結點開始,均可以很方便地訪問它的前驅結點和後繼結點。通常咱們都構造雙向循環鏈表。線程
雙鏈表的示意圖以下:設計
表頭爲空,表頭的後繼節點爲"節點10"(數據爲10的節點);"節點10"的後繼節點是"節點20"(數據爲10的節點),"節點20"的前繼節點是"節點10";"節點20"的後繼節點是"節點30","節點30"的前繼節點是"節點20";...;末尾節點的後繼節點是表頭。
不難看出,雙向鏈表的節點定義能夠用一個下面的結構體表示:
//雙向鏈表節點結構 typedef struct dlink_node { struct dlink_node *prev; struct dlink_node *next; void *val; //能存儲任意類型數據 }node;
咱們看看雙向鏈表刪除節點的操做,好比說下面這個單鏈表中咱們要刪除"節點30"。
刪除以前:"節點20"的後繼節點爲"節點30","節點30" 的前繼節點爲"節點20"。"節點30"的後繼節點爲"節點40","節點40" 的前繼節點爲"節點30"。
刪除以後:"節點20"的後繼節點爲"節點40","節點40" 的前繼節點爲"節點20"。
雙向鏈表刪除節點的關鍵代碼以下:
//刪除節點pindex pindex->next->prev = pindex->prev; pindex->prev->next = pindex->next; free(pindex); //注意釋放節點
咱們再來看看雙向鏈表添加節點的操做,好比說下面這個雙向鏈表在"節點10"與"節點20"之間添加"節點15"
添加以前:"節點10"的後繼節點爲"節點20","節點20" 的前繼節點爲"節點10"。
添加以後:"節點10"的後繼節點爲"節點15","節點15" 的前繼節點爲"節點10"。"節點15"的後繼節點爲"節點20","節點20" 的前繼節點爲"節點15"。
雙向鏈表添加節點的關鍵代碼以下:
//將pnode節點插入到pindex以前 pnode->prev = pindex->prev; pnode->next = pindex; pindex->prev->next = pnode; pindex->prev = pnode;
【福利】本身蒐集的網上精品課程視頻分享(上)
【系統設計】LRU緩存
【協議森林】05 我盡力 (IP協議詳解)
【數據結構與算法】 通俗易懂講解 位排序
【C++札記】C++11併發編程(一)開啓線程之旅
【C++札記】C/C++指針使用常見的坑
【C++札記】靜態庫和動態庫詳解(上)
碼農有道,爲您提供通俗易懂的技術文章,讓技術變的更簡單!