2016-01-09 95 views
-2
void del_duplicated(struct node *first) { 
    struct node *current = listfirst, *prev = listfirst, *tmp; 
    if (current == NULL) 
     printf("Nothing to delete !\n"); 
    while (current != NULL) { 
     /* Keeping traverse the list to find the duplicated elements. */ 
     prev = current; 
     current = current->next; 

     /* for the first and second duplicated node such as 1 1 2 3 5 */ 
     if (prev->data == listfirst->data && current->data == listfirst->data) { 
      listfirst = current->next; 
      printf("LIST FIRST NOW AT %d", listfirst->data); 
     } 
     /* The rest requirement such as 1 2 4 4 5 convert to 1 2 5 */ 
     else if ((prev->next)->data == (current->next)->data) { 
      (prev->next) = (current->next)->next; /*this is point 2 to 5*/ 
      tmp = current;     /*delete the node*/ 
      free(tmp); 
      tmp = current->next; 
      free(tmp); 
     } 
    } 
} 

我有一個鏈表問題,需要我從列表中刪除「2個重複節點」。 這就像1 1 2 3 5轉換爲2 3 5。 和1 2 4 4 5將被轉換爲1 2 5從排序的鏈接列表中一次刪除「2個重複」元素

但我的程序崩潰,因爲指針指向一個陌生的地方,我不知道爲什麼。 (.exe已停止工作) 我認爲我的移動指針的邏輯確定,但是.... error like this 我的邏輯附加在我的源代碼的註釋中。

我是一名在臺灣學習計算機科學的新手。 請原諒我的壞英語。

編輯 1小時後。

我在我的兩位法官聲明中添加了BREAK,並且運行良好。 但我不知道爲什麼。所有的

void del_duplicated(struct node *first) { 
    struct node *current = listfirst, *prev = listfirst, *tmp, *tmp2; 
    if (current == NULL) 
     printf("Nothing to delete !\n"); 
    while (current != NULL) { 
     /* Keeping traverse the list to find the duplicated elements. */ 
     prev = current; 
     current = current->next; 
     //printf("prev %d,current %d\n", prev->data, current->data); 
     //system("pause"); 
     /* for the first and second duplicated node such as 1 1 2 3 5 */ 
     if (prev->data == listfirst->data && current->data == listfirst->data) { 
      listfirst = current->next; 
      system("pause"); 
      break; 
     } 
     /* The rest requirement such as 1 2 4 4 5 convert to 1 2 5 */ 
     else if (current->data == (current->next)->data) { 
      (prev->next) = (current->next)->next; /* this is point 2 to 5 */ 
      tmp = current->next; 
      tmp2 = current;     /* delete the node */ 
      current = (current->next)->next; 
      free(tmp); 
      free(tmp2); 
      break; 
     } 
    } 
} 
+1

你的英語非常好。你應該花一些時間**學習調試**。它將爲您節省無數個小時的「爲什麼這不起作用」 – bolov

+0

如果您的列表沒有虛擬的第一個節點(這意味着您的第一個節點在第一個示例中保持值爲1),那麼您正在更改列表地址當你刪除你的第一個節點。您必須將列表的地址傳遞給您的函數才能執行此操作。例如'void del_duplicated(struct node ** first)'。否則,當你刪除第一個節點時,你在main()中沒有引用你的列表。 –

+0

非常感謝:D我會!!!我剛剛學習C 4個月前〜 – Alfons

回答

0
#include <stdio.h> 
#include <stdlib.h> 

typedef struct node NODE; 
struct node{ 
    int   data; 
    NODE  *next; 
    NODE  *prev; 
}; 


NODE * find_node(NODE *first, int value){ 
    while(first){ 
     if(first->data == value) 
      return first; 
     first = first->next; 
    } 
    return NULL; 
} 

NODE* delete_node(NODE **pnd){ 

    NODE *tmp, *nd; 

    if(!pnd || !*pnd) 
     return NULL; 

    nd =  *pnd; 
    tmp =  nd->next; 



    if(nd->next) 
     nd->next->prev = nd->prev; 

    if(nd->prev) 
     nd->prev->next = nd->next; 

    free(nd); 

    *pnd=NULL; 

    return tmp; 
} 


void del_duplicated(NODE **first) { 
    NODE *tmp, 
      *dup, 
      *current=*first; 
    int val; 
    while(current){ 

     dup = find_node(tmp,current->data); // find in next nodes 
     tmp = current->next; 
     val= current->data; 
     while(1){ 
      dup=find_node(tmp,val); 
      if(!dup) break; 

      while(dup){       // delete all occurences 
       if(dup == tmp) 
        tmp = dup->next; 
       delete_node(&dup); 
       dup=find_node(tmp,val); 
      } 
      delete_node(&current);    // delete current one aswell 
     }  
     current=tmp;         

    } 
} 


NODE *new_node(NODE *parent,int value){ 

    NODE *nd = malloc(sizeof(NODE)); 
    nd->prev = parent; 

    if(parent){ 
     nd->next =  parent->next; 
     if(parent->next) 
      parent->next->prev = nd; 

     parent->next = nd; 
    }else 
     nd->next =  NULL; 

    nd->data =   value; 

    return nd; 

} 



void free_nodes(NODE *root){ 
    NODE *tmp; 

    if(root && root->prev){ 
     root->prev->next = NULL; 
    } 
    while(root){ 
     tmp =    root; 
     root =    root->next; 
     free(tmp); 
    } 
} 

void print_nodes(NODE *root, char *text){ 

    if(text) 
     printf("%s:\n", text); 

    while(root){ 
     printf("%d ", root->data); 
     root = root->next; 
    } 
    printf("\n"); 
} 

int main(void){ 
    NODE  *root; 
    root =  new_node(NULL,10); 

    new_node(root, 25); 
    new_node(root, 25); 
    new_node(root, 25); 
    new_node(root, 20); 
    new_node(root, 15); 
    new_node(root, 16); 
    new_node(root, 16); 
    new_node(root, 5); 

    print_nodes(root ,"\nWith duplicated items"); 
    del_duplicated(&root); 
    print_nodes(root ,"\nDuplicated items removed"); 

    free_nodes(root); 
    return 0; 
} 
0

首先,你必須採用參數列表你的函數del_duplicated的, 使得它能夠刪除第一個元素了。使用struct node **first而不是 struct node *first。要刪除2個相等的元素,使用一個指向元素的指針並前進,直到元素的數據與其後繼數據相等。因爲你有一個指向元素的指針,所以你可以很容易地刪除元素及其後繼者。

void del_duplicated(struct node **first) 
{ 
    struct node **current = first; 

    if (current == NULL || *current == NULL) 
     return; 

    // One step forward as long as there is a a successor node 
    // and data of node and data of successor node are not equal 
    while ((*current)->next != NULL && 
      (*current)->data != (*current)->next->data) 
    { 
     current = &((*current)->next); 
    } 

    if ((*current)->next != NULL) 
    { 
     if ((*current)->prev != NULL) 
      (*current)->prev->next = (*current)->next->next; // successor of predecesor is successor of successor 
     if ((*current)->next->next != NULL) 
      (*current)->next->next->prev = (*current)->prev; // predecesor of successor of successor is predecesor 

     // delete this node and successor node 
     free((*current)->next); 
     free(*current); 
     *current = NULL // may be it was first 
    } 
} 
+0

我使用listfirst作爲全局變量,它運行良好,當涉及到正常刪除,如1 2 3 4 5 - > 1 2 3 5 感謝您的回覆,我會嘗試它以後〜 – Alfons

相關問題