最近實現了單鏈表的建立,插入,刪除,尋找元素,以及輸出,刪除鍊錶的操作。這裡記錄下自己對鍊錶的理解。
首先是鍊錶,鍊錶有兩個屬性,乙個是資料屬性(域),另乙個是指標屬性(域),鍊錶的理解通俗的來講可以想成老師,讓學生手拉手連線起來,這樣就形成了一條人形長鏈,每乙個學生,就是乙個 「結點」,老師是頭結點(head)。要乙個結點就找乙個學生拉上去;不要乙個結點就讓那個學生手放開,空出的兩個學生手拉在一起……1:動態申請記憶體 malloc 函式 (memory allocation)我也可以把鍊錶想象成一條鐵鍊,要乙個結點就焊接乙個上去;不要乙個就敲碎乙個,把敲碎那個的旁邊兩個重新焊接起來;要加乙個資料上去就把要插入的位置的那個節點給融開,把新的結點焊上去。
其原型是:
extern
void
*malloc
(unsigned
int num_bytes)
;
void
* 是未確定型別的指標,要使用者指定型別,如char*,
int*
,double
*若沒有指定則會報錯.
如果申請成功,則返回被指向的記憶體的指標,否則返回 null
與之相對應的是free()函式,用來釋放由malloc給指標變數申請記憶體空間。
其原型是:
void
free
(void
*p)
struct node
;
void
listinitiate
(node *
*head)
//二級指標
這裡傳遞的是主函式中指標變數head的位址,而不是值。
void
listdate
(node *
*head)
//二級指標
p2->next =
null
;//最後乙個結點指向null
}
在主函式中,我將頭指標的位址傳過去,因為如果將頭指標傳的值過去,是無法達到建立資料的效果,所以要傳遞指標的位址,也就是在listdate()函式的引數列表內要宣告乙個二級指標。
此函式的作用,先給p1, p2動態分配乙個大小為 sizeof(node) 的記憶體空間。
頭指標的指標域指向第乙個結點所在的記憶體位置。
錄入資料的結束條件為輸入的資料為0.
錄入第二個資料的時候,要將第乙個結點的指標域,指向第二個結點所在的記憶體位置。
即,錄入第n個資料,將第n - 1個結點的指標域,指向第 n 個結點所在的記憶體位置。
這就是鍊錶的連線處理,通過指標域,將乙個個結點連線起來,達到整體的目的。這也就存在乙個問題,不像陣列那樣,知道下標便可以直接輸出資料,而是讀取的時候都要從頭指標遍歷起。
注意 2 點:
最後乙個結點的指標域,一定指向null。
p -> next中儲存的,都是下乙個結點所在的記憶體位址,這個記憶體位址是由malloc函式分配的,是一整塊的,具有兩個資料域的。(這點要著重理解)
int
listinsert
(node *head,
int n,
int x)
if(k != n -1)
//若此時沒有指到第 n - 1個結點
return0;
if((p2 =
(node *
)malloc
(sizeof
(node)))
==null
)//新開闢乙個記憶體
exit(0
);else
}
假設要插入的為結點x
要實現在第n個結點前插入乙個資料,就必須得找到第n - 1個結點的位址,這樣才能將資料插在第n個後面。
當指標到達第n - 1這個位置後,就將x的指標域指向第n個結點所在的記憶體位址。
即該句:p2->next = p1->next;由於p1在前面指向了第n - 1個位址,故p1->next是第n個所在的記憶體位址。
最後令第n - 1個節點指向新開闢的記憶體位址即可實現成功加入資料。
int
listdelete
(node *head,
int n,
int*x)
if(k != n -1)
return0;
fn = p1->next;
//存放第 n 個指標位址
p1->next = p1->next->next;
//使第n-1個指標域指向第n+1個結點位址
free
(fn)
;//刪除完畢後要釋放該記憶體
return1;
}
刪除第n個元素,就必須先移動到第n - 1個位置,在將其前乙個結點(n-1)和其後乙個結點(n+1)連線起來,最後釋放該結點記憶體即可。
注意:p1->next = p1->next->next;中,p1在前面的迴圈中,指到了第n-1個結點,所以p1->next中存放的是下第n個結點的位址,即p1->next->next的意思就是取出第n個結點的指標域裡面的值,而裡面存放的是第n+1個結點位置。
p1->next = p1->next->next;也可以這樣想:
p
(n-1
)->next =
node
(n);
//第n個結點位址是儲存在前乙個結點指標域中的
node
(n)->next =
node
(n+1);
//第n個結點的指標域中存放是第n+1個結點的位置
p(n-1)
->next->next =
node
(n+1);
//故有...
我覺得還可以這樣思考:
賦值號的左邊是固定的,表示就是第n-1個結點的指標域,右邊是動態的,乙個next就表示向這鍊錶前面移動乙個,幾個移動幾次,這裡從n-1移動了兩次,故變成了第n+1個結點位置。
感覺第二種思考方式更簡單的…
啊,再次感覺指標理解起來難。
int
listlength
(node *head)
return i;
}
void
printlist
(node *head)
}
void
destorynode
(node *
*head)
//傳遞頭指標變數的位址進來
*head =
null
;//頭指標指向空,防止野指標。
printf
("釋放成功\n");
}
這裡注釋掉的兩段是我想看下鍊錶的鏈結方式,可以更加直觀的看到資料,也方便進一步理解鍊錶是如何乙個乙個通過指標鏈結起來的。
到此,鍊錶的一些基本操作已經完成(可能有錯誤的地方歡迎指出)。
記得當時在學習鍊錶的時候,理解能力不夠,便放棄了,經過了高中的洗禮,理解能力跟上了,再次看鍊錶的時候,一下子就理解了這個抽象的東東,開心啊。這篇博文就簡單的記錄下我對於鍊錶的理解吧哈哈哈。
順序鍊錶的實現和鍊錶查詢的實現
程式實現鍊錶的建立,鍊錶的查詢功能 create 方法實現了順序鍊錶的建立,並呼叫鍊錶查詢模組的find 方法 find 方法實現順序鍊錶的查詢 include define maxsize 100 定義乙個陣列的長度 定義乙個連續陣列sqlist typedefstructsqlistsqlist...
鍊錶原理及實現理解
鍊錶是有序的列表。鍊錶是以節點的方式來儲存,鏈式儲存 每個節點包含data域,next域,指向下乙個節點 鍊錶的各個節點不一定是連續的儲存 鍊錶分帶頭節點的節點和沒有帶頭結點的鍊錶 應用例項 實現 108好漢,無序 有序 package com.stone.datastructures author...
鍊錶的理解
鍊錶的理解 開發工具與關鍵技術 visual studio c 鍊錶,通過這段時間對鍊錶的理解。最終有了個人的理解。我對鍊錶的理解呢,就是乙個節點乙個節點連線起來的。節點由我們的資料結構構成,我們可以用 struct,class 去建立節點。開始的時候我也有嘗試著去用 union 去做連表,但是得出...