學習中總結出的鍊錶的高效寫法

2021-10-23 03:18:38 字數 3385 閱讀 5351

我們原本習慣用陣列來處理大量的資料,但是陣列的本質是線性表,對於資料的讀取,其時間複雜度為o(1),並且陣列本身所佔的空間很小,不需要額外的儲存空間來儲存邏輯關係。但陣列也有缺點,對於資料的插入刪除,大家估計想想就頭痛,就好比一群人在排隊,乙個人插了你的隊,從你到佇列的最後乙個人都要往後走幾步,此時心裡一萬隻草泥馬跑過。。。所以我們引入了鍊錶這個結構,它可以讓插入,刪除操作的時間複雜度極大的簡化。

我們可以想象乙個銀行,裡面的人與排隊不同,而是鬆散地處於銀行各處,要確定他們之間的順序,有乙個很好的辦法:讓每個人的手上拿著下乙個顧客位置的紙片,每辦完業務之後,就去通知下乙個顧客,而我們所要做的就是記住第乙個顧客的位置。所以具體而言每乙個顧客(資料)擁有著兩個型別的資料,即:原本的資訊——資料域,下乙個人的位置——指標域。我們還稱每個「顧客」為節點。鍊錶的本質就是一連串排列不規則卻擁有邏輯順序(先後順序)的節點的集合。順便說一下,這樣的結構占地位置更大(額外要儲存指標變數),而記憶體的棧區的儲存很有限,對於大量的資料,我們推薦利用malloc函式開拓記憶體的堆區(很大)來儲存。

以下是鍊錶的概念圖(本人靈魂畫師,敬請見諒)。date為資料域,pnext為指向下一節點的指標(指標域)。

鑑於鍊錶是由節點為主體,如果按照傳統的寫法,我們之後編寫函式可能會造成鍊錶和節點的混淆,無可避免會寫得很複雜,最關鍵的是,體現不出物件導向的思維方式。我參考了大牛的**,引入他的乙個結構,該結構用於管理整個鍊錶,我希望將這個結構稱之為鍊錶,以達到將節點與鍊錶嚴格區分起來的目的。具體來說,這個結構存有三類資料:

1):指向第乙個節點的指標 pfront

2):指向最後乙個節點的指標 prear

3):記錄整個鍊錶的節點個數 count

我們可以通過這個結構讓有關鍊錶函式的結構看起來很清晰,同時體現物件導向。我們以list為鍊錶,node為節點,以下是具體的定義方法:

struct node//定義節點

struct list//定義鍊錶

1.先是鍊錶的初始化

int

initlist

(list*

*pplist)

//傳入乙個想要指向list型別指標的位址(二級指標)

else

return0;

//初始化失敗返回0

}

這裡由於要改變指標的指向,所以引數要傳入二級指標

2.判斷鍊錶是否為空

int

isempty

(list*plist)

其中plist為指向該鍊錶區域的指標。

3.將節點插入鍊錶中

void

insertlist

(list*plist,node*pnode)

//傳入指向鍊錶的指標以及要插入的節點的指標

最後兩行在滿足if 和else 的條件下都要使用,所以提出來了。

4.遍歷函式

void

visitlist

(list*plist,

void

(visit)

(node*pnode)

)}

其中的visit是乙個指標函式,該指標指向返回值為空,引數型別為node*型的函式。倒數第三行能這麼寫是因為函式名就是該函式的位址。這麼做的目的是可以防止遍歷的反覆地重寫。下面舉個例子:我定義乙個顯示鍊錶資料的函式:

void

showdata

(node*pnode)

這時只要這麼表示(假設有乙個指向鍊錶的指標plist):

visitlist

(plist,showdata)

;

這樣就可以列印出煉表中所有節點的資料data了。

至於刪除整個鍊錶的函式也會用到遍歷,但是,我想在這裡給出乙個錯誤的方法

先定義刪除函式

void

deletelist

(node*pnode)

然後刪除整個鍊錶就是

visitlist

(plist,deletelist)

;

這是我給的乙個錯誤示範,為什麼會錯呢?

原因在於:你free掉了節點的空間,它不僅僅資料域被free了,指標域也沒了,ptemp=ptemp->pnext無法進行。

正確的方法為

void

deletelist

(list*plist)

}

5.插入鍊錶特定位置的函式

int

insert_list

(list*plist,

int n,node*pnode)

else

return0;

//不滿足條件則返回0

}else

if(n<=(plist-

>count)+1)

//判斷要插入的位置是否大於已有的節點數量+1

else

return0;

//不符合返回0

}}

6.刪除鍊錶特定位置的函式

int

delete_list

(list*plist,

int n)

if(plist-

>count==

1&&n!=1)

return0;

if(n>1)

if(n<=(plist-

>count))

//判斷要插入的位置是否小於等於已有的節點數量

else

return0;

//不符合返回0}}

}

鍊錶的總結

優雅的寫出鍊錶 6大學習技巧 2020.9.22 一 理解指標或引用的含義 示例 p next q 表示p節點的後繼指標儲存了q節點的記憶體位址。p next p next next 表示p節點的後繼指標儲存了p節點的下下個節點的記憶體位址。二 警惕指標丟失和記憶體洩漏 單鏈表 插入節點 在節點a和...

雙向迴圈鍊錶的學習總結

雙向迴圈鍊錶有兩個指標節點,乙個指向前驅,乙個指向後繼,可以向前和向後訪問任何資料。實現建立 刪除 新增 輸出雙向迴圈鍊錶的資料的c語言 雙向鍊錶的建立及插入乙個資料及輸出所有的資料 include includestruct node t node int main int ar char arg...

鍊錶的學習

鍊錶的每乙個元素由乙個儲存元素本身的節點和乙個指向下乙個元素的引用。1.靈活的記憶體動態管理,記憶體空間不是必須連續的 2.不必在建立時就確認大小,大小可以無限的延伸下去 3.插入和刪除資料的時間複雜度低,只有o 1 訪問查詢某個節點時,需要從頭開始進行訪問 function linkedlist ...