昨天晚上在學習數據結構關於鏈表的部分,理解鏈表沒什么難度,但是當自己動手寫程序的時候各種問題就出來了,感覺邏輯很正常但是總得不到正確的結果。
首先自己對C語言指針理解的不是很深入,在定義鏈表節點的結構體時,定義了一個指針類型的變量指向結構體如代碼所示:
1 typedef int status; 2 typedef struct Node{ 3 status data; 4 Node *next; 5 }Node,*linklist;
然后在main函數中定義一個指向結構體的指針變量如 linklist L;
在main函數之外聲明一個創建鏈表的函數
1 void Create_list(linklist L1,int n){ 2 linklist p; 3 L1 = (linklist)malloc(sizeof(Node)); 4 L1->next = NULL; 5 for(i = 0;i < n; i++){ 6 p = (linklist)malloc(sizeof(Node)); 7 p->data = i; 8 p->next = L1->next; 9 L1->next= p; 10 } 11 }
Create_list函數采用的事頭插法添加鏈表節點,經過main 函數的調用生成一個鏈表。但是問題來了當我在使用打印鏈表的函數進行打印時,鏈表L是沒有值的。我一直想不通,因為上述函數的邏輯是沒有錯的。為什么會出這樣的問題呢。我開始從Main函數進行分析,首先定義linklist L ;然后調用Create_list函數,把指針L傳給Create_list中的形參L1(指針類型),指針L和指針L1這兩個變量指向同一個地址,但實質上還是兩個指針變量,他們在內存中有自己的位置。當執行 L1 = (linklist)malloc(sizeof(Node));這條語句時L1將指向一個新節點的地址,這時L1和L中的保存的地址就已經不同了,接下來的操作都與指針L沒有任何關系了,這就是問題的所在。如何解決這個問題呢??
我們需要將指針L的地址(不是L指向的地址)傳過去,這樣Create_list函數中形參L1中保存的就是指針L的地址即指向指針的指針。之后用(*L1)的結果就是指向指針L指向的地址,相當於加了一層保護。代碼如下:
1 void Create_list(linklist *L1,int n){ 2 linklist p; 3 (*L1) = (linklist)malloc(sizeof(Node)); 4 (*L1)->next = NULL; 5 6 for(i = 0;i < n; i++){ 7 p = (linklist)malloc(sizeof(Node)); 8 p->data = i; 9 p->next = (*L1)->next; 10 (*L1)->next= p; 11 } 12 } 13 Main函數如下: 14 int main(){ 15 linklist L; 16 Create_list(&L,5); 17 return 0; 18 }