Алгоритм, осуществляющий сортировку массива из 100 000 целых чисел за 0.5 секунд, приведен ниже. Читайте комменты :) #include <conio.h> #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 } Время сортировки массива из 100000 элементов в указанной системе ~0.5 секунд. Сортировка методом Шелла ~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++; } } Этот код вставляется на место выделенного куска в функции сортировки. |