@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);
}


Буду признателен за помощь.
  • Вопрос задан
  • 185 просмотров
Решения вопроса 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]

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

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

Войти через центр авторизации
Похожие вопросы