Быстрая сортировка элементов массива
Алгоритм, осуществляющий сортировку массива из 100 000 целых чисел за 0.5 секунд, приведен ниже. Читайте комменты :)
Сортировка методом Шелла ~8 секунд.
Функция сортирует массив в порядке возрастания.
После сортировки, минимальный элемент можно достать следующим образом:
Если в классических методах для сортировки последовательности любой длины дополнительная память составляля пару байт, то данный метод требует ещё столько, сколько занимает массив. В итоге нужно (n*3) байт памяти, где n - размер массива.
P.S.
1. 16-ти разрядная сортировка(система счисления 65536) показала лучшие результаты.
2. Размер требуемой памяти не зависит от системы счисления.
3. Сортировку по убыванию можно сделать следующим образом:
#include <conio.h>Время сортировки массива из 100000 элементов в указанной системе ~0.5 секунд.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
struct el
{
int val;
el*next,*prev;
};
// структура для хранения промежуточных результатов сортировки
struct stack
{
el*cur,*mass;
int n,stackempty;
stack();
insert(int);
release();
reverserelease();
};
// конструктор
stack::stack()
{
n=0;
cur=mass=NULL;
stackempty=1;
}
// функция, возвращающая первый элемент стэка,
// удаляет первый, и второй становится первым.
stack::reverserelease()
{
int ret;
if(n==0)
return 0;
ret=mass->val;
if(mass->next!=NULL){
mass=mass->next;
delete mass->prev;
}
else
delete mass;
n--;
if(n==0)
stackempty=1;
return ret;
}
// функция, возвращающая последний элемент стэка,
// удаляет последний, и последним становится предпоследний.
stack::release()
{
int ret;
if(n==0)
return 0;
ret=cur->val;
cur=cur->prev;
if(cur==NULL)
delete mass;
else
delete cur->next;
n--;
if(n==0)
stackempty=1;
return ret;
}
// добавление элемента в стэк
stack::insert(int ins)
{
stackempty=0;
if(n==0){
mass=new el;
mass->prev=NULL;
mass->next=NULL;
mass->val=ins;
cur=mass;
n++;
return 0;
}
cur->next=new el;
cur->next->prev=cur;
cur->next->next=NULL;
cur->next->val=ins;
cur=cur->next;
n++;
return 0;
}
// собственно сортировка.
// p - указатель на исходный неотсортированный массив
// numb - последовательность целых индексов в порядке возрастания от 0 до len-1
// фактически сортируется эта последовательность, а исходная не меняется.
// len - длина массива
// base - система счисления, по которой происходит сортировка.
void bitsort(int*p,int*numb,int len,int base)
{
int i,j,k,step;
int bit,cbit;
switch(base)
{
//системой счисления определяется количество разрядов,
//по которым будет происходить сортировка.
//должна быть степенью двойки по понятным соображениям.
//здесь приведены не все возможные системы, кому мало, может дописать ещё.
case 2: step=1; break;
case 4: step=2; break;
case 8: step=3; break;
case 16: step=4; break;
case 32: step=5; break;
case 512: step=9; break;
case 65536: step=16; break;
default:
printf("Error in sorting base: %d",base);
return;
}
stack*st=new stack[base];
for(i=0;i<sizeof(int)*8;i=i+step)
{
cbit=(base-1)<<i;
for(j=0;j<len;j++)
{
bit=p[numb[j]]&cbit;
bit=bit>>i;
st[bit].insert(numb[j]);
}
k=0;
/*** этот код отвечает за построение возрастающей последовательности ***/
/**/ for(j=0;j<base;j++)
/**/ {
/**/ while(!st[j].stackempty)
/**/ {
/**/ numb[k]=st[j].reverserelease();
/**/ k++;
/**/ }
/**/ }
/*****************************************************************************/
if(k!=len)
{
printf("Error occured while sorting array");
return;
}
}
delete st;
}
// начало нашей проги
void main()
{
system("cls");
int z = 0;
int *p, *sorted, n = 0, i = 0, j = 0;
stack st;
unsigned int n_el = 0, max = 1024;
clock_t start = 0,end = 0;
float t1 = 0;
n = 10/*0000*/;
p = new int[n]; // выделение памяти для значений
sorted = new int[n]; // выделение памяти для номеров отсортированных чисел
srand((unsigned int)time(0l));
for(i = 0; i < n; i++)
{
p[i] = rand(); // заполнение массива произвольными числами
sorted[i] = i; // тоже заполняем
}
// выводим сгенеренные значения
for(i = 0; i < n; i++)
{
printf("%d\r\n",p[sorted[i]]);
}
printf("Press any key to begin sorting\r\n");
_getch(); // просим нажать на any key
start = clock(); // начинаем замер времени
bitsort(p, sorted, n, 65536); // <=== сортируем здесь
end=clock(); // заканчиваем подсчет времени
t1 = (float)(end-start) / CLK_TCK; // подсчет затраченного времени в секундах
printf("%lf\n",t1); // вывод результата
// выводим отсортированные значения
for(i = 0; i < n; i++)
{
printf("%d\r\n",p[sorted[i]]);
}
delete p; // удаляем массив со значениями
delete sorted; // удаляем массив с номерами отсортированных значений
printf("Press any key to continue");
while (!_getch()); // просим нажать на any key
}
Сортировка методом Шелла ~8 секунд.
Функция сортирует массив в порядке возрастания.
После сортировки, минимальный элемент можно достать следующим образом:
min=p[sorted[0]];Высокая скорость работы достигнута за счет использования больших объемов памяти.
Если в классических методах для сортировки последовательности любой длины дополнительная память составляля пару байт, то данный метод требует ещё столько, сколько занимает массив. В итоге нужно (n*3) байт памяти, где n - размер массива.
P.S.
1. 16-ти разрядная сортировка(система счисления 65536) показала лучшие результаты.
2. Размер требуемой памяти не зависит от системы счисления.
3. Сортировку по убыванию можно сделать следующим образом:
for(j=base-1;j>=0;j--)Этот код вставляется на место выделенного куска в функции сортировки.
{
while(!st[j].stackempty)
{
numb[k]=st[j].release();
k++;
}
}