@Nodar
Python, Ruby, JavaScript

Почему не работает мой mergesort?

Всем, привет.
Решил подучить алгоритмы, и писать их на чистом С, потому что и сам C знаю немного, но тоже хочу подтянуть. Решил начать с написания алгоритмов.

Уже несколько дней бьюсь надо merge sort, делаю по псевдокоду описанному в Introduction to Algorithms.

void
merge(int *array, int start, int mid, int end)
{ 

  int leftLen = mid - start,
      rightLen = end - mid,
      left[leftLen], right[rightLen],
      i, j, k;

  for (i = 0; i < leftLen; i++) {
    left[i] = array[start+i];
  }

  for (j = 0; j < rightLen; j++) {
    right[j] = array[mid+j];
  }

  i = 0;
  j = 0;
  
  for (k = start; k < end; k++) {
    if ((i < leftLen && left[i] < right[j]) || j >= rightLen) {
      array[k] = left[i];
      i++;
    } else {
      array[k] = right[j];
      j++;
    }
  }
}


void mergeSort(int *array, int start, int end)
{
  int mid = (start + end) / 2;
  if (start < end) {
    mergeSort(array, start, mid);
    mergeSort(array, mid+1, end);
    merge(array, start, mid, end);
  }
}


int
main(int argc, const char *argv[])
{
  int array[] = {3,2,6,4,1,8,7,9,5},
      arrayLen = sizeof(array)/sizeof(int);

  mergeSort(array, 0, arrayLen);
}


Буду признателен за помощь.
  • Вопрос задан
  • 187 просмотров
Решения вопроса 1
Mrrl
@Mrrl
Заводчик кардиганов
Видны две ошибки. Первая не должна влиять на результат, но может привести к выходу индекса за границу массива:
if ((i < leftLen && left[i] < right[j]) || j >= rightLen) {

В случае, когда j==rightLen, у вас будет проверяться элемент right[j]. Условия здесь надо поменять местами:
if ( j >= rightLen || (i < leftLen && left[i] < right[j])) {

Вторая - что элемент array[mid] не будет участвовать ни в первом, ни во втором рекурсивных вызовах mergeSort. Второй вызов надо было сделать
mergeSort(array, mid, end);
А чтобы не было бесконечной рекурсии, изменить условие в mergeSort на
if (start < end-1) {
(или на if(start < mid) ).

Ну, и в классическом С невозможна конструкция

int leftLen = mid - start,
      left[leftLen];

Там массивы могут быть только фиксированной длины, а для динамического захвата приходится использовать malloc. Но если компилируется, значит, ваша версия компилятора такое позволяет.

UPD. В С99 действительно возможны массивы переменной длины, и пишут, что gcc их поддерживает. Ну и ладно. Visual Studio такое не позволяет.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@Mercury13
Программист на «си с крестами» и не только
int left[leftLen]

Будь осторожен, на «боевых» задачах чревато переполнением стека. Стек вызовов невелик, всего ничего единицы мегабайт.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы