2016-01-06 154 views
0

我寫了一個函數,用於在鏈表的末尾插入一個節點。當我運行程序時,以及當我調用此函數時,程序停止工作。在鏈表的末尾插入

下面是函數:

void insert(node **head, int x) { 
    node *new = malloc(sizeof(node)); 
    new->data = x; 
    new->next = NULL; 

    node *temp = *head; 

    while (temp != NULL) { 
     temp = temp->next; 
    } 
    temp->next = new; 
} 

誰能告訴它是在哪裏去了?

+1

歡迎來到Stack Overflow。一般來說,「停止工作」並不足以說明問題。它會進入無限循環嗎?它是否會因分段錯誤或同等程序而崩潰?或者是別的什麼?其中一個要考慮的問題是「調試器顯示了什麼?」另一個是「當打印語句添加到代碼中時發生了什麼?」這些技巧中的一個或另一個是確定出現問題的必要步驟。請考慮創建一個MCVE([如何創建一個最小,完整和可驗證的示例?](http://stackoverflow.com/help/mcve)) –

回答

4
  1. while循環終止tempNULL。因此temp -> next將生成Segmentation Fault。您可以使用while(temp->next!=NULL)而不是while(temp!=NULL)

  2. 如果headNULL? (空鏈表)
    檢查是否head是否爲NULL

  3. 另外如果malloc失敗?

因此,解決辦法是:

void insert(node **head, int x) 
{ 
    node *new = (node *)malloc(sizeof(node)); 

    if(!new) 
    { 
     printf("Memory allocation failed!\n"); 
     exit(1); 
    } 
    new->data = x; 
    new->next = NULL; 

    node *temp = *head; 

    if(!temp) 
     *head = new; 
    else 
    { 
     while (temp->next != NULL) 
     { 
      temp = temp->next; 
     } 
     temp->next = new; 
    } 
    return ; 
} 
2

使用node**進行迭代。所以沒關係,如果列表是空的或沒有。迭代,直到找到節點nextNULL。你可以在目標上分配內存。

void insert(node **head, int x){ 

    node **ptr_new = head; 
    while(*ptr_new != NULL){ 
     ptr_new = &((*ptr_new)->next); 
    } 

    // now temp refers either to head or to next of the last node. 
    *ptr_new = malloc(sizeof(node)); 
    if (*ptr_new != NULL) 
    { 
     (*ptr_new)->next = NULL; 
     (*ptr_new)->data = x; 
    } 
} 

與您的原始代碼相反,您有一個指向新指針的指針,其中存儲了新節點的地址。在你原來的代碼中,你重複的時候temp不是NULL

while (temp != NULL) { 
    temp = temp->next; 
} 

while循環temp==NULL之後,因爲這是你的循環的終止條件。因爲你的程序停止工作,這裏temp->next = new;

+0

您還應該檢查'malloc()'成功 - 但該技術很有趣。 Steve Maguire也在「編寫固體代碼」中對此進行了描述。它的優點是它避免了特殊情況 - 因此有助於減少代碼膨脹。 –

2

有兩個問題與您的代碼:

  • ,直到它變成NULLtemp指針被推到列表的末尾,那時就爲時已晚將新指針存儲到其next成員,並嘗試調用未定義的行爲(您的系統上的Segmentation fault)。
  • 如果列表爲空,即使您在temp->next == NULL時停止循環,也不能以此方式存儲新項目。

也希望避免使用C++關鍵字來命名C代碼中的變量,因爲如果需要這樣做,將會更難將代碼遷移到C++。

此外,測試malloc失敗並返回指向新節點的指針或NULL失敗時會更加正確。

這裏是一個修正版本:

node *insert(node **head, int x) { 
    node *new_node = malloc(sizeof(node)); 
    if (new_node != NULL) { 
     new_node->data = x; 
     new_node->next = NULL; 

     node *temp = *head; 
     if (temp == NULL) { 
      *head = new_node; 
     } else { 
      while (temp->next != NULL) { 
       temp = temp->next; 
      } 
      temp->next = new_node; 
     } 
    } 
    return new_node; 
} 

您也可以使用指針的指針來遍歷列表:它是較爲複雜的,但更短的,你只有一個測試,以找出位置存儲new指針:

node *insert(node **head, int x) { 
    node *new_node = malloc(sizeof(node)); 
    if (new_node != NULL) { 
     new_node->data = x; 
     new_node->next = NULL; 

     node **np = head; 
     while (*np) { 
      np = &(*np)->next; 
     } 
     *np = new_node; 
    } 
    return new_node; 
} 
+0

我喜歡第二種方法。謝謝! – sstefan