Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
К тем примерно ста более-менее разным сортировкам, о которых мне известноВнушительная цифра. Не хотите опубликовать в виде статьи список своей коллекции? Хотя бы всего несколько строк на каждую сортировку:
А вот эта штука тут есть? https://fuchsia.googlesource.com/fuchsia/+/refs/heads/master/src/graphics/lib/compute/hotsort/
procedure qSort_insSort(var m : Array of LongWord; l,r : LongWord);
procedure ASM_QSort assembler;
ASM
@@START_SORT:
MOV R10,RDX
SUB R10,20 // Если отрезок меньше 20 элементов сортируем вставками (так быстрее)
CMP R10,RCX
JA @@ASM_QSort // Иначе сортируем быстрой сортировкой со срединным опорным элементом
// Сортировка вставками --------------------------------------------------------
MOV R8,RCX // i:=0;
@@I_BEGIN:
ADD R8,4 // i:=i+1;
CMP R8,RDX // while (i<=r) do
JA @@END // i>r
MOV R9,R8 // j:=i;
@@J_BEGIN:
CMP R9,0 // j<=0
JNA @@I_BEGIN // Оканчиваем итерацию j
MOV R10,R9 // (j)
SUB R9,4 // (j-1)
MOV EAX,DWord[R9] // m[j-1]
MOV EBX,DWord[R10] // m[j]
CMP EAX,EBX // m[j-1]<=m[j]
JNA @@I_BEGIN // Оканчиваем итерацию j
MOV DWord[R9],EBX
MOV DWord[R10],EAX
JMP @@J_BEGIN
// Qsort с рекурсией -----------------------------------------------------------
@@ASM_QSort:
MOV R8,RCX
ADD R8,RDX
SHR R8,3
SHL R8,2
MOV R10D,DWord[R8] // находим срединный элемент
MOV R8,RCX // i:= P1; j:= P2;
MOV R9,RDX
@@i_START: // while (o < m[j]) do dec(j);
MOV EAX,DWord[R8]
CMP EAX,R10D
JNL @@j_START // если больше или равно
ADD R8,4
JMP @@i_START
@@j_START: // while (PLongWord(j)^ > o) do dec(j,4);
MOV EBX,DWord[R9]
CMP EBX,R10D
JNG @@j_STOP // если меньше или равно
SUB R9,4
JMP @@j_START
@@j_STOP:
CMP R8,R9 // if (i <= j) then
JG @@NO_XCHG // если меньше или равно
MOV EAX,DWord[R8] // temp:=m[i]; m[i]:=m[j]; m[j]:=temp;
MOV EBX,DWord[R9]
MOV DWord[R8],EBX
MOV DWord[R9],EAX
ADD R8,4 // inc(i); dec(j);
SUB R9,4
@@NO_XCHG:
CMP R8,R9 // until (i > j);
JNG @@i_START // если меньше или равно
CMP RCX,R9 // if (P1 < j) then
JNB @@SORT1 // Jump, если больше или равно
PUSH R8 // i
PUSH RDX // p2
// Первый аргумент (p1) уже в регистре RCX
MOV RDX,R9 // Устанавливаем второй аргумент (j)
CALL ASM_QSort // вызываем Сортировку первого отрезка (рекурсивно)
POP RDX // p2
POP R8 // i
@@SORT1:
CMP R8,RDX // if (i < P2) then
JNB @@END // Jump, если больше или равно
MOV RCX,R8 // Устанавливаем первый аргумент (i)
// Второй аргумент (p2) уже в регистре RDX
JMP @@START_SORT // вызываем Сортировку второго отрезка (Без рекурсии)
@@END:
END;
// Вызов процедуры сортировки
begin
ASM
CMP R8,R9 // Если L>=R
JNB @@NO_RUN
CMP RDX,R9 // Если LENGTH(M)>=R
JA @@NO_RUN
CMP R8,0 // Если L<0
JB @@NO_RUN
CMP RDX,0 // Если LENGTH(M)=0
JE @@NO_RUN
LEA RDX,[RCX+R9*4]
LEA RCX,[RCX+R8*4]
CALL ASM_QSort
XOR RAX,RAX
JMP @@END
@@NO_RUN:
MOV RAX,1
@@END:
END;
end;
Какой у вас интересный и выразительный Паскаль получился...
const SS = 100;
var a: array[1 .. SS]of longword;
var i: longint;
begin
for i := 1 to SS do a[i] := random(SS);
qSort_insSort(a, 0, SS - 1);
for i := 1 to SS - 1 do
if a[i - 1] > a[i] then begin
writeln('error i = ', i, ' a[i-1] = ', a[i - 1], ' a[i] = ', a[i]);
halt(2)
end;
end.
Procedure test();
const n=16;
var m:Array of LongWord;
i:LongWord;
begin
SetLength(m,n);
Randomize;
for i:=0 to Length(m)-1 do m[i]:=Random(9000)+1000;
for i:=0 to n-1 do WRITE(inttostr(m[i])+' ');
WRITELN('');
qSort_insSort(@m[0],0,n-1);
for i:=0 to n-1 do WRITE(inttostr(m[i])+' ');
WRITELN('');
end;
ASM
CMP RDX,RCX // Если L>=R
JNB @@NO_RUN
CMP RSI,RCX // Если LENGTH(M)>=R
JA @@NO_RUN
CMP RDX,0 // Если L<0
JB @@NO_RUN
CMP RSI,0 // Если LENGTH(M)=0
JE @@NO_RUN
LEA RAX,[RDI+RCX*4]
LEA RCX,[RDI+RDX*4]
MOV RDX,RAX
CALL ASM_QSort
XOR RAX,RAX
JMP @@END
@@NO_RUN:
MOV RAX,1
@@END:
END;
void MQSort(vector<int> &m, int l, int r) {
LOOP:
if (r - l <= 20) {
int i = l + 1, j;
while (i <= r) {
j = i++;
while (j > 0 && m[j - 1] > m[j]) {
swap(m[j - 1], m[j]);
--j;
}
};
return;
}
int o = m[(l + r)/2], i = l, j = r;
do {
while (m[i] < o) ++i;
while (o < m[j]) --j;
if (i <= j)
swap(m[i++], m[j--]);
} while (i <= j);
if (l < j) MQSort(m, l, j);
if (i < r) {
l = i;
goto LOOP;
}
}
// Комбинированная сортировка --------------------------------------------------
procedure qSort_insSort2(var m : Array of LongWord; l,r : LongWord);
procedure ASM_QSort assembler;
ASM
@@START_SORT:
MOV R8,RCX // i:=0; Используется в обоих алгоритмах экономим 3 байта
MOV RAX,RDX
SUB RAX,RCX
CMP RAX,R11
JGE @@Q_Sort // Иначе сортируем быстрой сортировкой со срединным опорным элементом
// Сортировка вставками --------------------------------------------------------
//MOV R8,RCX // i:=0;
@@I_BEGIN:
ADD R8,R12 // i:=i+1;
CMP R8,RDX // while (i<=r) do
JA @@END // i>r
MOV R9,R8 // j:=i;
@@J_BEGIN:
CMP R9,RCX // j<=0
JNA @@I_BEGIN // Оканчиваем итерацию j
MOV R10,R9 // (j)
SUB R9,R12 // (j-1)
MOV EAX,DWord[R9] // m[j-1]
MOV EBX,DWord[R10] // m[j]
CMP EAX,EBX // m[j-1]<=m[j]
JNA @@I_BEGIN // Оканчиваем итерацию j
MOV DWord[R9],EBX // Меняем местами
MOV DWord[R10],EAX
JMP @@J_BEGIN
// Qsort с рекурсией -----------------------------------------------------------
@@Q_Sort:
//MOV R8,RCX
ADD R8,RDX
SHR R8,3
SHL R8,2
MOV R10D,DWord[R8] // находим срединный элемент
MOV R8,RCX // i:= P1;
MOV R9,RDX // j:= P2;
@@i_START: // while (o < m[j]) do dec(j);
MOV EAX,DWord[R8]
CMP EAX,R10D
JNL @@j_START // если больше или равно
ADD R8,R12
JMP @@i_START
@@j_START: // while (PLongWord(j)^ > o) do dec(j,4);
MOV EBX,DWord[R9]
CMP EBX,R10D
JNG @@j_STOP // если меньше или равно
SUB R9,R12
JMP @@j_START
@@j_STOP:
CMP R8,R9 // if (i <= j) then
JG @@NO_XCHG // если меньше или равно
MOV EAX,DWord[R8] // temp:=m[i]; m[i]:=m[j]; m[j]:=temp;
MOV EBX,DWord[R9]
MOV DWord[R8],EBX
MOV DWord[R9],EAX
ADD R8,R12 // inc(i); dec(j);
SUB R9,R12
@@NO_XCHG:
CMP R8,R9 // until (i > j);
JNG @@i_START // если меньше или равно
CMP RCX,R9 // if (P1 < j) then
JNB @@SORT1 // Jump, если больше или равно
PUSH R8 // i
PUSH RDX // p2
// Первый аргумент (p1) уже в регистре RCX
MOV RDX,R9 // Устанавливаем второй аргумент (j)
CALL ASM_QSort // вызываем Сортировку первого отрезка (рекурсивно)
POP RDX // p2
POP R8 // i
@@SORT1:
CMP R8,RDX // if (i < P2) then
JNB @@END // Jump, если больше или равно
MOV RCX,R8 // Устанавливаем первый аргумент (i)
// Второй аргумент (p2) уже в регистре RDX
JMP @@START_SORT // вызываем Сортировку второго отрезка (Без рекурсии)
@@END:
END;
begin
ASM
CMP R8,R9 // Если L>=R
JNB @@NO_RUN
CMP R9,RDX // Если R>LENGTH(M)
JA @@NO_RUN
CMP R8,0 // Если L<0
JB @@NO_RUN
CMP RDX,0 // Если LENGTH(M)=0
JE @@NO_RUN
LEA RDX,[RCX+R9*4]
LEA RCX,[RCX+R8*4]
MOV R11,100 // Будем хранить константу сравнения в регистре R11 так экономим 1 байт инструкций на каждом цикле
MOV R12,4
CALL ASM_QSort
XOR RAX,RAX
JMP @@END
@@NO_RUN:
MOV RAX,1
@@END:
END;
end;
И стандартом С++ прямо запрещено использовать быструю сортировку, так как std::sort всегда должна быть по порядку NlogN.
Насчет Шелла вы, возможно, не поняли о чем речь.
Что касается, что миллиард — это много, то это почти смешно.
поэтому правильное утверждение «существует много алгоритмов с худшим случаем NlogN» и более того поразрядные сортировки работают стабильно на любых данных с O(N).
И ещё о сортировках