Ваш код не компилируется.Чтобы перейти к g++ -Wall -Werror
, мне нужно было добавить следующие строки в начало файла:
#include <iostream>
using namespace std;
Ваш код читает только из массива a
и записывает в массив b
.Нигде «отсортированное» содержимое из b
не копируется обратно в a
.
Я предполагаю, что вы хотите, чтобы это произошло в merge()
, то есть путем добавления в конец функции:
for(int i=low; i<high; i++)
a[i] = b[i];
Кроме того, имеется ошибка off-by-one в main()
: mergesort()
ожидает, что high
будет общим количеством сортируемых элементов, а нет индекс самого высокого элемента в массиве:
mergesort(a,b,0,num);
С этими изменениями код компилирует и выводит правильный результат
-78 10 12 23 24 41 43 45 56 90 98 123
РЕДАКТИРОВАТЬ
Передача массива b
также не требуется, поскольку в действительности это необходимо только для выполнения слияния.Следовательно, код может быть обновлен следующим образом:
void merge(int*,int,int,int,int);
//mergesort
void mergesort(int *a, int low, int high)
{
...
mergesort(a,low,pivot1);
mergesort(a,pivot1,pivot2);
mergesort(a,pivot2,high);
merge(a,low,pivot1,pivot2,high);
}
//merge
void merge(int *a, int low, int pivot1, int pivot2, int high)
{
int b[high];
...
}
int main()
{
int a[] = {12,10,43,23,-78,45,123,56,98,41,90,24};
int num = sizeof(a) / sizeof(*a);
mergesort(a,0,num);
for(int i=0; i<num; i++)
cout<<a[i]<<" ";
cout<<endl;
}
РЕДАКТИРОВАТЬ 2
Потребление памяти на merge()
может быть уменьшено, поскольку при каждом вызове он сортирует только срез a[low..high-1]
.Следовательно, код можно обновить следующим образом:
//merge
void merge(int *a, int low, int pivot1, int pivot2, int high)
{
int b[high - low]; // slice a[low..high - 1] to be sorted
int i = 0; // running index in b[]
...
// replace slice a[low.. high - 1] with sorted result
for (i = low; i < high; i++)
a[i] = b[i - low];
}
БОНУС
Полный код упрощен и более читабелен:
#include <iostream>
using namespace std;
static void merge(int *a,
const unsigned int low, const unsigned int pivot1,
const unsigned int pivot2, const unsigned int high);
// mergesort (recursive)
static void mergesort(int *a, const unsigned int low, const unsigned int high)
{
const unsigned int slice = high - low;
// terminate recursion
if (slice < 2)
return;
if (slice < 3) {
// can't recurse for slice of length 2; just sort using 2 partitions
merge(a, low, low, low + 1, high);
return;
}
const unsigned int third = slice / 3;
const unsigned int pivot1 = low + third;
const unsigned int pivot2 = high - third;
// recurse
mergesort(a, low, pivot1);
mergesort(a, pivot1, pivot2);
mergesort(a, pivot2, high);
// merge
merge(a, low, pivot1, pivot2, high);
}
// merge
static void merge(int *a,
const unsigned int low, const unsigned int pivot1,
const unsigned int pivot2, const unsigned int high)
{
int sorted[high - low]; // slice a[low..high - 1] to be sorted
int *store = sorted; // running pointer into sorted[]
unsigned int partition1 = low; // running index a[low .. pivot1 - 1]
unsigned int partition2 = pivot1; // running index a[pivot1 .. pivot2 - 1]
unsigned int partition3 = pivot2; // running index a[pivot2 .. high - 1]
while ((partition1 < pivot1) &&
(partition2 < pivot2) &&
(partition3 < high)) {
if (a[partition1] < a[partition2])
*store++ = a[partition1] < a[partition3] ? a[partition1++] : a[partition3++];
else
*store++ = a[partition2] < a[partition3] ? a[partition2++] : a[partition3++];
}
while ((partition1 < pivot1) &&
(partition2 < pivot2)) {
*store++ = a[partition1] < a[partition2] ? a[partition1++] : a[partition2++];
}
while ((partition2 < pivot2) &&
(partition3 < high)) {
*store++ = a[partition2] < a[partition3] ? a[partition2++] : a[partition3++];
}
while ((partition1 < pivot1) &&
(partition3 < high)) {
*store++ = a[partition1] < a[partition3] ? a[partition1++] : a[partition3++];
}
while (partition1 < pivot1)
*store++ = a[partition1++];
while (partition2 < pivot2)
*store++ = a[partition2++];
while (partition3 < high)
*store++ = a[partition3++];
// replace slice a[low.. high - 1] with sorted result
for (unsigned int i = low; i < high; i++)
a[i] = sorted[i - low];
}
int main()
{
int a[] = {12,10,43,23,-78,45,123,56,98,41,90,24};
// int a[] = {-78,10,12,23,24,41,43,45,56,90,98,123};
// int a[] = { 4, 3, 2, 1, 0};
// int a[] = { 3, 2, 1, 0};
// int a[] = { 2, 1, 0};
// int a[] = { 1, 0};
// int a[] = { 0};
const unsigned int num = sizeof(a) / sizeof(*a);
mergesort(a, 0, num);
for (unsigned int i = 0; i < num; i++)
cout << a[i] <<" ";
cout << endl;
}
БОНУС 2
Повторно реализованоmerge()
функция:
static void merge(int *a,
const unsigned int low, const unsigned int pivot1,
const unsigned int pivot2, const unsigned int high)
{
unsigned int slice = high - low;
int sorted[slice]; // slice a[low..high - 1] to be sorted
unsigned int store = 0; // running pointer into sorted[]
unsigned int partition1 = low; // running index a[low .. pivot1 - 1]
unsigned int partition2 = pivot1; // running index a[pivot1 .. pivot2 - 1]
unsigned int partition3 = pivot2; // running index a[pivot2 .. high - 1]
while (store < slice) {
int next;
if (partition1 < pivot1) {
// partition1 is not exhausted yet
next = a[partition1];
if (partition2 < pivot2) {
// partitions 1 & 2 are not exhausted yet
if (partition3 < high) {
// all partitions are not exhausted yet
if (next < a[partition2]) {
if (a[partition2] < a[partition3])
partition1++; // p1 < p2 < p3
else if (next < a[partition3])
partition1++; // p1 < (p3 || p2)
else
next = a[partition3++]; // p3 <= p1 < p2
} else if (a[partition2] < a[partition3])
next = a[partition2++]; // p2 < p3 <= p1
else
next = a[partition3++]; // p3 <= p2 <= p1
} else if (next < a[partition2])
partition1++; // p1 < p2 [p3]
else
next = a[partition2++]; // p2 <= p1 [p3]
} else if (partition3 < high) {
// partition2 is exhausted, compare p1 & p3 only
if (next < a[partition3])
partition1++; // p1 < p3 [p2]
else
next = a[partition3++]; // p3 <= p1 [p2]
} else
// partitions 2 & 3 are exhausted, copy from p1
partition1++; // p1 [p2, p3]
} else if (partition2 < pivot2) {
// partition1 is exhausted, compare p2 & p3 only
next = a[partition2];
if (partition3 < high) {
// partitions 2 & 3 are not exhausted
if (next < a[partition3])
partition2++; // p2 < p3 [p1]
else
next = a[partition3++]; // p3 <= p2 [p1]
} else
// partitions 1 & 3 are exhausted, copy from p2
partition2++; // p2 [p1, p3]
} else {
// partitions 1 & 2 are exhausted, copy from p3
next = a[partition3++]; // p3 [p1, p2]
}
// store smallest entry
sorted[store++] = next;
}
// replace slice a[low.. high - 1] with sorted result
for (unsigned int i = low; i < high; i++)
a[i] = sorted[i - low];
}