2011-03-07 95 views
1

我正在學習鏈接列表操作並且有一個與參數傳遞有關的問題。鏈接列表引用指針

問題1: 我正在用三個值1-> 2-> 3創建一個簡單的鏈表。我試圖打印它。 以下是我的代碼。我在我的main中創建一個節點「first」,並將它傳遞給「createlinkedlist」方法。我正在使用一個指針「頭」並在方法中更新它。但是我發現在「createlinkedlist」方法之外正確保留了「head」的值。我不明白這是怎麼發生的。我想我應該使用的借鑑參數傳遞喜歡

void createLinkedList(struct node * & head)void createLinkedList(struct node ** head)

,而不是

void createLinkedList(struct node * head) 

以獲得正確的價值觀體現在函數外。我在這裏錯過了什麼?爲什麼我能夠在printList方法內看到正確的值?

struct node 
{ 
    int data; 
    struct node * next; 

}; 

void createLinkedList(struct node * head) 
{ 

    struct node * second = (node *)malloc(sizeof(node)); 
    struct node * third = (node *)malloc(sizeof(node)); 

    head->data = 1; 
    head->next = second; 

    second->data = 2; 
    second->next = third; 

    third->data = 3; 
    third->next = NULL; 

} 

void printList(struct node * first) 
{ 
struct node * current = first; 
while(current) 
{ 
printf("%d",current->data); 
current = current->next; 
} 
} 
void main() 
{ 
    struct node * first = (node *)(malloc(sizeof(node))); 
    createLinkedList(first); 
    printList(first); 
} 

問題2:我使用的是同一個程序同上,但加入了推送功能

void push(struct node *& first, int data) 
{ 
    struct node * newnode = (node*)malloc(sizeof(node)); 
    newnode->data = data; 
    newnode->next = first; 
    first = newnode; 
} 

現在我明白了,除非我用的是「&」在推的第一個參數( ),我無法在printList方法中看到更新。這對我來說很有意義,因爲我們通常需要使用參考參數來使得在函數外部看到的局部功能改變。所以如果列表需要一個參考參數,爲什麼它在問題1中的行爲不同。 請致電讓我知道。

+1

語言? C還是C++? – duffymo 2011-03-07 20:46:30

+0

*和&取消。它本質上意味着[struct node head] – rkg 2011-03-07 20:48:00

+1

@Ravi:我不認爲這是一個聲明的情況。 – Lars 2011-03-07 20:54:34

回答

0

既然你是在談論引用我假設你正在使用C++。

你想在struct node *& head傳遞,如果你要去指針修改head,但在你的例子中,你希望只修改頭節點本身,而不是指向它,這是爲什麼你只是傳遞一個指針來讓你查找地址。當你通過取消引用的head->...指針,你正在尋找起來head在內存中的位置,然後移動到其datanext場。或者,你可以在頭通作爲參考struct node & head,並修改之類的東西head.data直接。

push需要有一張參考first指針struct node *& first),或指針first指針struct node **first),這樣你實際上可以修改pointer itself。這是發生了什麼事就行了:

first = newnode; 

另外,如果你使用的struct node **first,你會怎麼做:

*first = newnode; 

這裏push了這兩種情況修改指針struct node,而不是修改一個struct node本身。

+0

很多人。它有很大的幫助!我thk我現在得到它。 – user457660 2011-03-08 00:18:17

2

關於問題1)

你不改變指針頭在你的createLinkedList方法;您正在更改頭指向的節點的內容。所以你當然會在調用createLinkedList之後看到這種改變。

對於問題2)

在第二種情況下,你實際上是添加新節點,你需要改變頭指針指向鏈表的新負責人,而在第一種情況下,你保持列表頭部穩定,並將新節點添加到列表的尾部。所以你不需要把列表頭的新地址返回給調用者,因爲頭的地址沒有改變。

我還要創建一個節點構造函數:

 
struct node * make_node(int data) 
{ 
    struct node * tmp = (node *)malloc(sizeof(node)); 
    if (!tmp) { 
    /* error handling for malloc failure */ 
    } 
    tmp->next = NULL; 
    tmp->data = data; 
    return tmp; 
} 

另一點:

如果我是你,如果我寫的添加節點列表的頭推功能,我會明確地返回列表的新掌門人:

 
struct node * push(const struct node * head, int data) { 
    struct node * fresh = make_node(data) 
    fresh->next = head; 
    return fresh; 
} 

調用此像這樣:

 
struct node * head = make_node(1); 
head = push(head, 2); 

這比理解推動(頭部,1)改變頭部更容易理解。但這是一個風格問題。

+0

是的,我同意你的觀點,JeSuisse更容易理解,而不必處理文獻。參數,但是我在鏈表上看到的大部分書籍和鏈接都是在ref中實現的。參數。所以這讓我想到,從內存和空間利用率以及性能角度來看,這是否是非常有效的方式。 – user457660 2011-03-08 00:17:08

+0

關於問題1.在做一些研究之後,我的理解是,「第一」和「頭」都只是複製其指向同一個內存位置。所以當我修改其中一個時,變化應該反映到另一個上。 – user457660 2011-03-08 07:12:15

+0

Reg。引用與返回值:實際上引用*的效率更高一些,因爲編譯器不需要將返回值複製到頭變量中,但這是按照幾條機器指令的順序排列的,這些指令可以忽略不計。 – JeSuisse 2011-03-08 11:09:25

1

變化

struct node * first = (node *)(malloc(sizeof(node))); 
struct node * second = (node *)(malloc(sizeof(node))); 
struct node * third = (node *)(malloc(sizeof(node))); 

部分

struct node * first = (struct node *)(malloc(sizeof(struct node))); 
struct node * second = (struct node *)(malloc(sizeof(struct node))); 
struct node * third = (struct node *)(malloc(sizeof(struct node))); 

。由於您在沒有「typedef」的情況下初始化「節點」,因此每次使用「節點」之前都需要寫入「struct」。