В этом небольшом посте, я выкладываю тривиальные реализации различных методов сортировки массивов с разными типами данных. Все предложенные способы сортируют массивы по возрастанию (хотя, очень легко сделать так, чтобы весь код стал универсальным: допустим, можно слегка модифицировать листинги таким образом, чтобы каждая из функций сортировки принимала на вход еще и операцию, с помощью которой будет выполнено упорядочивание).
Итак, код на D:
import std.stdio;
void exch(T)(ref T x, ref T y)
{
T tmp = x;
x = y;
y = tmp;
}
T[] selectionSort(T)(T[] x)
{
T[] res = x.dup;
for (size_t i = 0; i < res.length - 1; i++)
{
size_t min = i;
for (size_t j = i + 1; j < res.length; j++)
{
if (res[j] < res[min]) min = j;
}
exch(res[i],res[min]);
}
return res;
}
T[] bubbleSort(T)(T[] x)
{
T[] res = x.dup;
for (size_t i = 0; i < res.length; i++)
{
for (size_t j = 0; j < res.length - i - 1; j++) { if (res[j] > res[j+1]) exch(res[j],res[j+1]);
}
}
return res;
}
T[] shellSort(T)(T[] x)
{
T[] res = x.dup;
size_t d = x.length;
for (size_t i = d/2; i > 0; i /= 2)
{
for (size_t j = i; j < d; j++) { for (size_t k = j; k >= i && res[k-i] > res[k]; k -= i)
{
exch(res[k],res[k-i]);
}
}
}
return res;
}
T[] gnomeSort(T)(T[] x)
{
T[] res = x.dup;
size_t i = 0;
while (i < res.length)
{
if (i == 0 || res[i-1] <= res[i]) i++;
else
{
exch(res[i],res[i-1]);
i--;
}
}
return res;
}
T[] insertionSort(T)(T[] x)
{
T[] res = x.dup;
for (size_t i = 0; i < res.length; i++)
{
for (size_t j = i; j && res[j] < res[j-1]; j--)
{
exch(res[j],res[j-1]);
}
}
return res;
}
T[] shakerSort(T)(T[] x)
{
T[] res = x.dup;
size_t beg,end;
for (size_t i = 0; i < res.length/2; i++) { beg = 0; end = res.length - 1; do { if (res[beg] > res[beg+1]) exch(res[beg],res[beg+1]);
beg++;
if (res[end-1] > res[end]) exch(res[end-1],res[end]);
end--;
}
while (beg <= end); } return res; } T[] combSort(T)(T[] x) { T[] res = x.dup; size_t size = res.length; if (res && size) { size_t jump = size; bool swapped = true; while (jump > 1 || swapped)
{
if (jump > 1) jump /= 1.24733;
swapped = false;
for (size_t i = 0; i + jump < size; i++)
{
if (res[i+jump] < res[i])
{
exch(res[i+jump],res[i]);
swapped = true;
}
}
}
}
return res;
}
T[] oddEvenSort(T)(T[] x)
{
T[] res = x.dup;
bool sorted = false;
template cycle(string num)
{
const char[] cycle = "for (int i = " ~ num ~ " ; i < res.length - 1; i += 2) { if (res[i] > res[i+1]) {
exch(res[i],res[i+1]);
sorted = false;
}
}";
}
while (!sorted)
{
sorted = true;
mixin(cycle!"1");
mixin(cycle!"0");
}
return res;
}
T[] stoogeSort(T)(ref T[] x,size_t i, size_t j)
{
// first call: stoogeSort(x,0,x.length - 1)
if (x[j] < x[i]) exch(x[j],x[i]); if (j - i > 1)
{
size_t t = (j - i + 1) / 3;
stoogeSort(x, i , j-t);
stoogeSort(x, i+t, j );
stoogeSort(x, i , j-t);
}
return x;
}
T[] quickSort(T)(T[] x)
{
uint partition(T)(T[] x)
{
if (x.length < 2) return 0;
auto pivot = x[$-1];
uint i = -1, j = x.length-1;
while(i < j || i == -1)
{
i++;
while(x[i] < pivot) i++;
j--;
while(i < j && x[j] > pivot) j--;
if(i < j && j < x.length) exch(x[i], x[j]); } exch(x[i], x[$-1]); return i; } if (x.length > 1)
{
exch(x[$/2], x[$-1]);
auto p = partition(x);
quickSort(x[0 .. p]);
quickSort(x[p + 1 .. $]);
}
return x;
}
Процедура exch – вспомогательная и служит для того, чтобы поменять значения некоторых двух переменных местами.
P.S: Код, конечно, не идеальный, но все-таки он написан мной. Кроме того, возможно, я выложу более универсальную версию данных алгоритмов.