2012-11-19 12 views
5

Jestem studentem pierwszego roku i poznaję teraz listę linków. Kiedy sortuję bąbelkowo listę połączoną, występuje błąd segmentu, GDB wskazuje na funkcję bubble(), i = ptr-> elem. Nie wiem, co to jest przyczyną. proszę pomóżcie wymyślić.sortowanie bąbelkowe z listą linków

`

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#include <string.h> 

define  i_track(n) printf ("The %s's is %d.\n", #n, (n)) 
define  s_track(n) printf ("%s.\n", #n); 


typedef struct tag_node 
{ 
    int elem; 
struct tag_node *next; 
}NODE, *SLINK; 

void node_track (SLINK list); 
NODE *node_generate (void); 
void init_list (SLINK *header, int len); 
SLINK locate_cur (SLINK list, int target_elem); 
void insert_node (SLINK *list, int new_elem, int tag_elem); 
SLINK traverse_list (SLINK list); 
void list_info (SLINK list, int node_elem); 
void bubble (SLINK list); 
void swap (int *a, int *b); 

int main (int argc, char *argv[]) 
{ 
int len; 
SLINK list = node_generate(); 
printf ("Input a number for length of the link.\n"); 
scanf ("%d", &len); 
s_track(init_start.); 
init_list (&list, len); 
s_track(init_end.); 
traverse_list (list); 
bubble (list); 

return EXIT_SUCCESS; 
} /* ---------- end of function main ---------- */   

NODE *node_generate (void) /* generate a node */ 
{ 
NODE *new_node = malloc (sizeof (NODE)); 
if (NULL == new_node) 
{ 
    printf ("ERROR: malloc failed.\n"); 
    exit (EXIT_FAILURE); 
} 
memset (new_node, 0, sizeof(NODE)); 
return new_node; 
} 

void insert_node (SLINK *list, int new_elem, int tag_elem) 
/* insert a node */ 
{ 
NODE *new_node = node_generate(); 
NODE *cur = *list; 
new_node->elem = new_elem; 
if ((int)NULL == tag_elem) 
{ 
    new_node->next = (*list)->next; 
    (*list)->next = new_node; 
} 
else 
{ 
    *list = locate_cur (cur, tag_elem); 
    new_node->next = (*list)->next; 
    (*list)->next = new_node; 
} 
} 

void init_list (SLINK *header, int len) 
/* generate a linked-list and assign it*/ 
{ 
srand ((unsigned) time(0)); 
int elem; 
for (int i = 0; i < len; i++) 
    /* skip number 4 since I dislike it */ 
    { 
     elem = rand() % 100; 

     if (4 == elem/10) 
     { 
      elem = elem + 50; 
     } 
     if (4 == elem % 10) 
     { 
      elem = elem + 5; 
     } 
     if (0 == elem % 100) 
     { 
      elem = elem + 999; 
     } 
     insert_node (header, elem, (int)NULL); 
    } 
} 

SLINK traverse_list (SLINK list) 
/*traverse list */ 
{ 
SLINK ptr = list; 
for (int node_num = 0; ptr != NULL; ptr = ptr->next) 
{ 
    ++node_num; 
    list_info (ptr, node_num); 
} 
return list; 
} 

void list_info (SLINK list, int node_num) 
/* used for traversed_list() */ 
{ 
if (1 == node_num % 10 && 11 != node_num) 
{ 
    printf ("The %dst element is %d.\n", node_num, list->elem); 
} 
else if (2 == node_num % 10 && 12 != node_num) 
{ 
    printf ("The %dnd element is %d.\n", node_num, list->elem); 
} 
else if (3 == node_num % 10 && 13 != node_num) 
{ 
    printf ("The %drd element is %d.\n", node_num, list->elem); 
} 
else 
{ 
    printf ("The %dth element is %d.\n", node_num, list->elem); 
} 
} 

SLINK locate_cur (SLINK list, int target_elem) 
/* locate previous of a node */ 
{ 
NODE *prev, *cur; 
prev = node_generate(); 
cur = node_generate(); 
for (prev = list, cur = list->next; NULL != cur && target_elem != cur->elem; prev = cur, cur = cur->next) 
    ; 
return cur; 
} 

void node_track (NODE *flag) 
{ 
printf ("The flag element is %d.\n", flag->elem); 
} 

void bubble (SLINK list) /* bubble sort */ 
{ 
s_track(bubble_start); 
list = list->next; 
SLINK ptr, header; 
ptr = list; /*GDB point to here*/ 
int i =0, j = 0; 
for (; NULL != list; list = list->next) 
{ 
    for (ptr = list; NULL != ptr; ptr = ptr->next); 
    { 
     j = list->elem; 
     i = ptr->elem; 
    // if (ptr->elem > list->elem) 
     if (i > j) 
      swap (&(ptr->elem), &(list->elem)); 
    } 
} 
s_track(bubble_end); 
} 

void swap (int *a, int *b) 
{ 
*a = (*a)^(*b); 
*b = (*a)^(*b); 
*a = (*a)^(*b); 
} 

`

+0

Konwersja oparta na Xor nie jest sensowna. W '# define' na początku brakuje' # '. –

+0

Można użyć 'calloc()' zamiast 'malloc()', a następnie 'memset()'. Test 'if ((int) NULL == tag_elem) jest ciekawy; ale cel "tag_elem" jest w najlepszym razie ciekawy i mam pewne trudności ze zrozumieniem jego znaczenia, szczególnie, że zawsze jest 'NULL', gdy 'insert_node' jest wywoływany z wewnątrz' init_list() '. –

Odpowiedz

1

Celem tag_elem w init_list() jest bardzo niejasny. Zmodyfikowałem kod, aby wyeliminować tę zmienną, a następnie uruchomiłem ją i określiłem 5 jako wartość wejściową. Daje to:

Input a number for length of the link. 
5 
init_start.. 
init_end.. 
The 1st element is 0. 
The 2nd element is 12. 
The 3rd element is 8. 
The 4th element is 99. 
The 5th element is 7. 
The 6th element is 63. 
bubble_start. 
Segmentation fault: 11 

Dlaczego 6 artykułów jest drukowanych, gdy zażądano 5? Przy wielokrotnym wykonywaniu wartość w pierwszym elemencie wynosi zawsze 0 (3 powtórzenia).

Ten problem można rozwiązać poprzez zmianę traverse_list() takiego:

SLINK traverse_list(SLINK list) 
{ 
    assert(list != 0); 
    SLINK ptr = list->next; 
    for (int node_num = 0; ptr != NULL; ptr = ptr->next) 
     list_info(ptr, ++node_num); 
    return list; 
} 

Co ciekawe, kod w bubble() już pomija, że ​​pierwsza pozycja na liście.

Jednak wewnętrzna pętla w bubble() ma błąd:

for (ptr = list; NULL != ptr; ptr = ptr->next); 
{ 
    j = list->elem; 
    i = ptr->elem; 
// if (ptr->elem > list->elem) 
    if (i > j) 
     swap (&(ptr->elem), &(list->elem)); 
} 

To może być łatwiej sprawdzić, czy zapisać go jako:

for (ptr = list; NULL != ptr; ptr = ptr->next) 
    ; 
{ 
    j = list->elem; 
    i = ptr->elem; // When this is executed, ptr == NULL! 
    if (i > j) 
     swap (&(ptr->elem), &(list->elem)); 
} 

Nie chcesz, że średnik . Mając to stałe, kod działa OK:

Input a number for length of the link. 
5 
init start. 
init end. 
The 1st element is 12. 
The 2nd element is 19. 
The 3rd element is 99. 
The 4th element is 92. 
The 5th element is 28. 
traverse 1 end. 
bubble_start. 
bubble_end. 
sort end. 
The 1st element is 99. 
The 2nd element is 92. 
The 3rd element is 28. 
The 4th element is 19. 
The 5th element is 12. 
traverse 2 end. 

Oczywiście, nieco zmodyfikowany zestaw druku diagnostycznej, ale dane są sortowane w kolejności malejącej. Wygląda na to, że działa również na większych zestawach; Próbowałem 55 bez awarii, niektóre powtórzenia w danych, a wyniki posortowane w malejącej kolejności.

+0

dzięki za pomoc. Naprawiłem to z twoją pomocą, usuwając głupi błąd półkolumny. dla init_list(), ponieważ nie podoba mi się liczba 4, więc funkcja wygląda dziwnie i niejasno. Wiem, że wartość pierwszego węzła to 0, to nie błąd, pierwotna funkcja, element węzła to połączenie, to po prostu tak: 'union {char * s; int n;}, pierwszy węzeł został przydzielony przez ciąg, więc w bubble(), został pominięty. Dziękuję bardzo. –