Сортировка слиянием на массиве Int C++

Я пытаюсь создать программу сортировки слиянием на массиве int, но у меня продолжают возникать проблемы с выполнением этой сортировки слиянием, она вызывает ошибку сегмента, но я не могу найти в этом ничего плохого. В void mergesort, когда я ставлю сначала <= last, то появляется ошибка сегмента, если нет, то 5 5 5 5 печатается.

#include <iostream>

 using namespace std;


void merge(int *arr, int size, int first, int middle, int last)
{
    int temp[size];
    for(int i = first; i<=last; i++)
    {
       temp[i] = arr[i];
    }
    int i=first, j=middle+1, k=0;
    while(i<=middle && j<=last)
    {
       if(temp[i] <= temp[j])
       {
          arr[k] = temp[i];
          i++;
       }
       else
       {
          arr[k]=temp[i];
          j++;
       }
       k++;
    }
    while(i<=middle)
    {
       arr[k]=temp[i];
       k++;
       i++;
    }
}

void mergesort(int *arr, int size, int first, int last)
{
    if(first<last)
    {
       int middle = ( first + last )/2;
       mergesort(arr,size,first,middle);
       mergesort(arr,size,middle+1,last);
       merge(arr,size,first,middle,last);
    }
}
int main()
{
    cout <<"Him";
    const int size = 10;
    int numbers [] = {5,10,1,6,2,9,3,8,7,4};
    mergesort(numbers,size,0,9);
    for( int i= 0; i<size; ++i)
    {
        cout << numbers[i] << " ";
    }
    return 0;
}

4 ответа

Решение

Есть (по крайней мере) две ошибки. Это:

else
{
   arr[k]=temp[i];                                          
   j++;
}

должно быть так:

else
{
   arr[k]=temp[j];                                          
   j++;
}

и это:

int i=first, j=middle+1, k=0;

должно быть так:

int i=first, j=middle+1, k=first;

В общем, вы должны научиться шагать по коду, по крайней мере, помещая диагностические операторы здесь и там. Как только вы это освоите, вы можете перейти к хорошему отладчику.

Стандартная библиотека уже реализует функцию, которая корректно объединяется: std::inplace_merge, Реализация адаптирована из этого более общего поста

void mergesort(int * first, int * last)
{
    std::ptrdiff_t N = std::distance(first, last);
    if (N <= 1) return;                   
    int * middle = std::next(first, N / 2);
    mergesort(first, middle); 
    mergesort(middle, last);  
    std::inplace_merge(first, middle, last); 
}

int main()
{
    cout <<"Him";
    const int size = 10;
    int numbers [] = {5,10,1,6,2,9,3,8,7,4};
    mergesort(numbers, numbers+size);
    for( int i= 0; i<size; ++i)
    {
        cout << numbers[i] << " ";
    }
    return 0;
}

Предложение 1:

Вместо этой строки:

int temp[size];

Если вам нужен массив динамического размера, используйте:

int temp = new int[size];

Затем, когда вы закончите с этим

delete[] temp;

Изменить: Как Нил предложил использовать std::vector, может быть более полезным, чем массивы в таких ситуациях (если вы можете использовать его).

Ваш код содержит 3 ошибки, также вы можете уменьшить длину кода, если это необходимо.

void merge(int *arr, int size, int first, int middle, int last)
{
    int temp[size];
    for(int i = first; i<=last; i++)
      temp[i] = arr[i];
    int i=first, j=middle+1, k=first; // 1st Change, Set k to first instead of 0
    while(i<=middle && j<=last)
    {
       if(temp[i] <= temp[j])
          arr[k++] = temp[i++];
       else
          arr[k++]=temp[j++]; // 2nd Change, use j instead of i
    }
    while(i<=middle)
       arr[k++]=temp[i++];
    while(j<=last)    // 3rd Change you missed this case
        arr[k++]=temp[j++];
}

Живой код

Другие вопросы по тегам