2015-02-19 3 views
1

Вот некоторые из моего кодасоздание сортировки слияния, которая принимает LinkedList в качестве входных данных

listnode *mergesort(struct listnode *list){ 
    struct listnode *L, *R, *head; 
    int i = 0; 
    head = list; 
    while (list->next != NULL){ 
     if (i%2 == 0){    //it splits the linkedlist into 2 segments 
            //it adds the elements in the linked list           
            // alternatively. 
            //to a linked list R & L 
      L=list->next; 
      list->next = L->next; 
      i=i+1; 
     } 
     else{ 
      R= list->next; 
      list->next = R->next; 
      i=i+1; 
     } 
     list = list->next; 

    } 
    MergeLists(mergesort(L),mergesort(R)); 
} 

Я постоянно получаю ошибку сегментации и не могу понять, что проблема есть.

+0

Как насчет работает под отладчиком? Вы должны быть в состоянии выяснить причину довольно быстро. – Praetorian

+0

Попробуйте выполнить компиляцию с информацией об отладке ('-g' для gcc/clang), затем используйте' catchsegv', 'valgrind' и/gdb', чтобы найти, где произошла ошибка. –

+0

спасибо, но действительно ли код подходит вам? – user4581941

ответ

0

Во-первых, то, что делает ваш «подсчет», - это перемещение left на единицу, когда число равно, и делает то же самое с right, когда число нечетное. Не говоря уже о том, что left и right неинициализированы, если в списке есть только один элемент, а последняя строка цикла может привести к разыменованию нулевого значения.

Во-вторых, вам нужно каким-то образом пометить конец списка left, иначе ваш слияние будет делать то же самое снова и снова, пока вы не переполните стек.

Мы можем сделать это, установив последний указатель в левой половине равным NULL. Имейте в виду, что MergeLists придется исправить все это, чтобы снова сделать один хороший список.

попробовать что-то вроде этого:

listnode *mergesort(listnode *list) { 
    listnode *left = list, *right = list, *prev, *end = list; 

    if (list == 0) { return list; } 

    // move right once for every two we move end, so that we divide the middle 
    while (end != 0) { 
    end = end->next; 
    prev = right; // keep track of the node before the start of right 
    right = right->next; 

    if (end != 0) { 
     end = end->next; 
    } 
    } 


    if (left->next == right) { 
    // TODO swap items if necessary 
    return left; 
    } 

    prev->next = 0; // split the list 
    left = mergesort(left); 
    right = mergesort(right); 
    // TODO join left and right by calling MergeLists or whatever 
    return left; 
} 

Схема указателей на работе:

prev->next = 0 removes -----| 
          v 
list -> [1] -> [2] -> [3] -> [4] -> [5] -> [6] 
left ----^     ^
right -------------------------| 
+0

Спасибо, но где в вашем коде указывают на другую половину связанного списка (слева)? – user4581941

+0

слева указывает на начало половины и справа указывает на начало другой половины –

+0

@ user4581941 См. Диаграмму –

0

Две вещи, которые я заметил: 1. int i = 0; значит, я всегда буду ровным. Является ли значение «i» значением в узле списка? 2. вернуть MergeLists (L, R); находится внутри оператора while, поэтому цикл будет завершен.

+0

Спасибо, я только что зафиксировал MergeLists (L, R) в цикле while, но int i = 0 инициализирует «i», чтобы я мог добавлять элементы связанного списка в качестве альтернативы , «i» не имеет связи с узлом, «i» - это просто переключатель от 0 до 1; если его 0 добавить элемент в L в противном случае добавить его в R – user4581941

Смежные вопросы