Это попытка заставить кучи сортировать кучи исключительно с помощью вызовов функций. Проблема в том, что для его завершения требуется слишком много времени, дольше, чем для простой пузырьковой сортировки, написанной в том же проекте, почти 100 секунд против 42 пузырька с 100000 записей в порядке убывания. Слияние и быстрая сортировка не прошли ни секунды. Не говоря уже о том, что он падает на 100000, если компилятору не удается выполнить оптимизацию хвостового вызова.
Раньше происходило аварийное завершение, некоторые детали реализаций сделаны для того, чтобы происходили хвостовые вызовы. Он был проверен на нисходящих, восходящих и случайно распределенных данных. Некоторые изменения были также сделаны, чтобы исправить то, насколько медленно это было, что придает ему запутанный вид.
int heap_sort_step(int v[], int len, int i){
int nextl = 2 * i + 1, nextr = nextl + 1;
char bfl = (nextl<len)|((nextr<len)<<1);
switch(bfl)
{
case 3:
case 2:
while(v[i] > heap_sort_step(v, len, nextr))
swap(v + i, v + nextr);
case 1:
while(v[i] > heap_sort_step(v, len, nextl))
swap(v + i, v + nextl);
default:
return v[i];
}
}
void heap_sort(int v[], int len){
return (len > 1)?
(heap_sort_step(v, len, 0),
heap_sort(v + 1, len - 1)):
NULL;
}
heap_sort (int v [], int len) берет массив и его размер и строит минимальную кучу для каждого элемента в массиве, используя heap_sort_step (), упорядочивая его. Хвостовые вызовы необходимы здесь.
heap_sort_step (int v [], int len, int i) принимает массив, его размер и индекс для построения кучи, с уравнениями, как показано в nextl и nextr, 2i + 1 и 2i + 2, начиная с i = 0. «bfl» - это трюк для оптимизации (небольшие улучшения по сравнению с использованием ifs), чтобы решить, к каким ветвям перейти или просто вернуть текущее значение, посмотрев, есть ли еще пункты впереди. Коммутатор использует падение и находится там, где строится куча, 3 и 2 означают, что есть вещи справа (0b11 и 0b10), а 1 означает, что есть вещи слева (0b01), поведение по умолчанию возвращает текущее число. Раньше это было написано как:
int heap_sort_step(int v[], int len, int i){
int nextl = (((i + 1) * 2) - 1), nextr = nextl + 1;
if(nextl < len)
while(v[i] > heap_sort_step(v, len, nextl))
swap(v + i, v + nextl);
if(nextr < len)
while(v[i] > heap_sort_step(v, len, nextr))
swap(v + i, v + nextr);
return v[i];
}
Что касается рекурсивного шага, он сравнивает текущее число с возвращаемым значением из следующего вызова функции, и если он больше, он меняет местами, если нет, происходит каскадный возврат обратно в корень.
На данный момент я почти уверен, что это просто плохая реализация, и хочу знать, является ли это проблемой сложности, вызванной изменениями, или чем-то еще. Можно ли сделать так, чтобы она конкурировала с mergesort и quicksort, используя одну и ту же концепцию? Это должно быть O n (log (n)), верно?