#ifndef _INCLUDED_L3_SORT_H #define _INCLUDED_L3_SORT_H // *Sorting methods comparison* Copyright (C) Krzysztof Bosak, 1999-12-30...2000-06-16 // All rights reserved. // kbosak@box43.pl // http://www.kbosak.prv.pl // ALWAYS: n == length_of_string_to_sort #include #include #include #include #include "l3_array.h" #include "l3_heap.h" #include "l3_ptr.h" #include "l3_str.h" #include "l3_rand.h" #include "l3_tool.h" //typedef char TEST_TYPE; //typedef int TEST_TYPE; //typedef double TEST_TYPE; typedef ContainerTester TEST_TYPE; template void RemoveRepetitionsFromSortedVector(array_container& vec) { if(vec.empty()) { return; } int write=1; for(int read=1; read void ShellSort(object_type * const arr, int n) { const int SHELLSORT_STEPS[]={1, 2, 4, 8, 16, 32, 64, 128, 256, 1024, 2048, 4096}; const double _log_2_inv=3.3219280948873623478703194294894;//1./log(2); const int ind=static_cast(log(n)*_log_2_inv); assert(ind>=0); assert(SHELLSORT_STEPS[ind]<=n); assert(static_cast(ind) < sizeof(SHELLSORT_STEPS)/sizeof(SHELLSORT_STEPS[0])); for(int gapcounter=ind; gapcounter>=0; gapcounter--) { const int gap=SHELLSORT_STEPS[gapcounter]; //cout<0; j-=gap) if(t inline void Swap(object_type &a, object_type &b) { const object_type tmp=a; a=b; b=tmp; } template inline void BubbleSort(object_type * const arr, int n) { assert(arr!=NULL); assert(n>=1); for(int i=0; ii; j--) if(arr[j] inline void BubbleSortW(object_type * const arr, int n) { assert(arr!=NULL); assert(n>=1); for(int i=n; i!=0; i--) for(int j=1; j inline void ShakerSort(object_type * const arr, int n) { assert(arr!=NULL); assert(n>=1); int left=1, right=n-1, k=n-1; do { int j; for(j=right; j>=left; j--) if(arr[j] inline void InsertSortW(object_type * const arr, int n) { assert(arr!=NULL); assert(n>=1); for(int i=1; i0; j--) if(t inline void QuickSortW(object_type * const arr, int n) { assert(arr!=NULL); assert(n>=0);// important because of recursive calls if(n==0) return;// important because of recursive calls int i=0, k=n-1; object_type t=arr[k>>1]; do { while(arr[i]k) break; if(i!=k) { const object_type temp=arr[i]; arr[i]=arr[k]; arr[k]=temp; } k--; i++; }while(i<=k); if(i inline void _QuickSortW2(object_type * const arr, int n) { assert(arr!=NULL); assert(n>=0);// important because of recursive calls if(n<=30) return;// important because of recursive calls int i=0, k=n-1; object_type t=arr[k>>1]; do { while(arr[i]k) break; if(i!=k) { const object_type temp=arr[i]; arr[i]=arr[k]; arr[k]=temp; } k--; i++; }while(i<=k); if(i inline void QuickSortW2(object_type * const arr, int n) { _QuickSortW2(arr, n); InsertSortW(arr, n); } template inline void HeapSortW(object_type * const arr, int n) { assert(arr!=NULL); assert(n>=1); int array_index; for(array_index=1; array_index>1; const object_type t=arr[child]; while(parent>=0 && arr[parent]>1; } assert(child>=0); assert(child1) { const object_type t=arr[array_index]; arr[array_index]=arr[0]; int parent=0; int child=1; while(child=0); assert(parent inline void HeapSortW_InsertSortW(object_type * const arr, int n) { assert(arr!=NULL); assert(n>=1); if(n<=100) { InsertSortW(arr, n); return; } int size; for(size=1; size>1; const object_type t=arr[child]; while(parent>=0 && arr[parent]>1; } assert(child>=0); assert(child 1) { const object_type t=arr[size]; arr[size]=arr[0]; int parent=0; int child=1; while(child=0); assert(parent inline void HeapSort(object_type * const arr, int n) { assert(arr!=NULL); assert(n>=1); growing_arrayheap HEAP; HEAP.setsize(n+1); int i; for(i=0; i inline void HeapSortNR(object_type * const arr, int n) { assert(arr!=NULL); assert(n>=1); if(n==1) return; int l=(n>>1)+1; int ir=n; int i; int j; object_type * const ra=&arr[0]-1;// This is allowed by The Standard, NuMega DevPartner is wrong here. This strange array indexing saves operations later in this function. //SmartPtr ra(&arr[0]-1, &arr[0], n); object_type rra; for(;;) { if(l>1) { --l; rra=ra[l]; } else { rra=ra[ir]; ra[ir]=ra[1]; if(--ir==1) { ra[1]=rra; break; } } i=l; j=l<<1; while(j<=ir) { if(j void QuickSortNR2(object_type * const arr_arg, const int n) { assert(arr_arg!=NULL); assert(n>=1); object_type * const arr=arr_arg-1;// This is allowed by The Standard, NuMega DevPartner is wrong here. This strange array indexing saves operations later in this function. int i,ir=n,j,k,l=1; int jstack=0; object_type a; const int SWITCH_TO_INSERTSORT=7; const int MAX_STACK_SIZE=64; //const double factor=2/log(2); //const int MAX_STACK_SIZE=static_cast(ceil(log(n)*factor));// 2*log2(N) //cout<<'<'<'< istack(MAX_STACK_SIZE);// should be static but DLLs... int istack[MAX_STACK_SIZE]; for(;;) { if(ir-l=1; i--) { if(arr[i]>1; PSwap(arr[k],arr[l+1]); if(arr[ir]=MAX_STACK_SIZE) { cerr<<"PURE QUICKSORT FAILED! WHAT A STRANGE DATASET. SWITCHING TO HEAPSORT."<= j-l) { istack[jstack]=ir; istack[jstack-1]=i; ir=j-1; } else { istack[jstack]=j-1; istack[jstack-1]=l; l=i; } } } #undef PSwap } #include template void STLSort(object_type * const arr_arg, int n) { assert(arr_arg!=NULL); assert(n>=1); std::sort(arr_arg, &arr_arg[n]); } #include template void STLStableSort(object_type * const arr_arg, int n) { assert(arr_arg!=NULL); assert(n>=1); std::stable_sort(arr_arg, &arr_arg[n]); } int BUCKETSORT_BUFFER[128]; inline void BucketSort(char * const arr, int n)// Fastest char sorting... { // Valid for char of range 0...127 assert(arr!=NULL); assert(n>=1); memset(BUCKETSORT_BUFFER, 0, 128*sizeof(int)); char *tab2=arr+n; const char * const tab3=arr; do { tab2--; BUCKETSORT_BUFFER[static_cast(*tab2)]++; }while(tab2>tab3); unsigned char i=0; do { while(BUCKETSORT_BUFFER[i]!=0) { BUCKETSORT_BUFFER[i]--; *tab2=static_cast(i); tab2++; } i++; }while(i<128); } ///////////////////////////////////////////////////////////////////////////// #ifdef SORT_TESTING #define ADD_SORT_FUNCTION(sfun) { (void(*)(TEST_TYPE *,int))(sfun), #sfun }, struct SortingFunction { void (*function)(TEST_TYPE *, int); TextString function_name; }; SortingFunction SORTING_FUNCTIONS[]= { // ADD_SORT_FUNCTION(ShellSort)// O(N^1.27); anyway slow implementation (or weak algorithm...) // ADD_SORT_FUNCTION(BubbleSortW) // ADD_SORT_FUNCTION(BubbleSort) // ADD_SORT_FUNCTION(ShakerSort)// BEST BubbleSort (N^2!) // ADD_SORT_FUNCTION(InsertSortW)// BEST O(N^2), weak for ReverseSortedWaveFiller // ADD_SORT_FUNCTION(QuickSortW)// Depreferred against heapsorts, // O(N*log2(N)) but O(N^2) in pesimistic case, but wins with SortedWaveFiller, // ReverseSortedWaveFiller, ConstantFiller // ADD_SORT_FUNCTION(HeapSortW) // ADD_SORT_FUNCTION(HeapSortW_InsertSortW) //ADD_SORT_FUNCTION(HeapSort)// Uses heap container (complex). //SortingFunction( (void(*)(TEST_TYPE *,int))(QuickSortNR2), "ddd"), ADD_SORT_FUNCTION(QuickSortNR2)//The Best Of All. BEST OF ALL O(N*log2(N)), wins with RandomMessFiller, // outperforms GNU qsort in all cases. //ADD_SORT_FUNCTION(QuickSortW) //ADD_SORT_FUNCTION(QuickSortW2) ADD_SORT_FUNCTION(STLSort)// STL ADD_SORT_FUNCTION(HeapSortNR)// Most Reliable Of All. ADD_SORT_FUNCTION(STLStableSort)// STL // ADD_SORT_FUNCTION(BucketSort)// BEST of all for char sorting, DANGER: limited chars <=127 {NULL, NULL} }; bool IsSorted(const TEST_TYPE *origchain, const TEST_TYPE *chain, int length, int spectrum_min, int spectrum_width) { const int spectrum_max=spectrum_min+spectrum_width-1; int i; for(i=0; i checked; checked.setsize(length); checked.fill(true); for(i=0; i0); assert(repetitions>0); assert(spectrum_min<256); assert(spectrum_min+spectrum_width<256); assert(randomseed>0); autoarray test(length); autoarray orig(length); for(int f=0; sfun[f].function!=NULL; f++) { cout<(spectrum_min); orig=test; sfun[f].function(&test[0], length); IsSorted(&orig[0], &test[0], length, spectrum_min, spectrum_width); cout<<"sort,"; cout.flush(); for(i=0; i(spectrum_min+static_cast(spectrum_width)*i/length); orig=test; sfun[f].function(&test[0], length); IsSorted(&orig[0], &test[0], length, spectrum_min, spectrum_width); cout<<"one,"; cout.flush(); for(i=0; i(spectrum_min+static_cast(spectrum_width)*i/length); test[length/2]=static_cast(spectrum_min+RAND.irandom(spectrum_width)); orig=test; sfun[f].function(&test[0], length); IsSorted(&orig[0], &test[0], length, spectrum_min, spectrum_width); cout<<"three,"; cout.flush(); for(i=0; i(spectrum_min+static_cast(spectrum_width)*i/length); test[length/2]=static_cast(spectrum_min+RAND.irandom(spectrum_width)); test[length/4]=static_cast(spectrum_min+RAND.irandom(spectrum_width)); test[static_cast(length*.75)]=static_cast(spectrum_min+RAND.irandom(spectrum_width)); orig=test; sfun[f].function(&test[0], length); IsSorted(&orig[0], &test[0], length, spectrum_min, spectrum_width); cout<<"+wave,"; cout.flush(); for(i=0; i(spectrum_min+i%spectrum_width); orig=test; sfun[f].function(&test[0], length); IsSorted(&orig[0], &test[0], length, spectrum_min, spectrum_width); cout<<"-wave,"; cout.flush(); for(i=0; i(spectrum_max-i%spectrum_width); orig=test; sfun[f].function(&test[0], length); IsSorted(&orig[0], &test[0], length, spectrum_min, spectrum_width); cout<<"revsort,"; cout.flush(); for(i=0; i(static_cast(spectrum_width)*i/length); orig=test; sfun[f].function(&test[0], length); IsSorted(&orig[0], &test[0], length, spectrum_min, spectrum_width); cout<<"rand,"; cout.flush(); for(int r=0; r(spectrum_min+RAND.irandom(spectrum_width)); orig=test; sfun[f].function(&test[0], length); IsSorted(&orig[0], &test[0], length, spectrum_min, spectrum_width); } cout<<"OK.\n"; cout.flush(); } } void TestSortAnyLength(const SortingFunction * const sfun, int length, int repetitions, int spectrum_min, int spectrum_width, int randomseed=1234) { cout<<"length=1:\n"; cout.flush(); TestSort(sfun, 1, repetitions, spectrum_min, spectrum_width, randomseed); cout<<"length=2:\n"; cout.flush(); TestSort(sfun, 2, repetitions, spectrum_min, spectrum_width, randomseed); cout<<"length=3:\n"; cout.flush(); TestSort(sfun, 3, repetitions, spectrum_min, spectrum_width, randomseed); cout<<"length="<<(length/2)+1<<":\n"; cout.flush(); TestSort(sfun, (length/2)+1, repetitions, spectrum_min, spectrum_width, randomseed); cout<<"length="< &mess, int spectrum_min, int spectrum_width) { assert(spectrum_min<256); assert(spectrum_min+spectrum_width<256); const int imax=mess.size(); for(int i=0; i &mess, int spectrum_min, int spectrum_width) { assert(spectrum_min<256); assert(spectrum_min+spectrum_width<256); for(int i=0; i &mess, int spectrum_min, int spectrum_width) { assert(spectrum_min<256); assert(spectrum_min+spectrum_width<256); int i; for(i=0; i &mess, int spectrum_min, int spectrum_width) { assert(spectrum_min<256); assert(spectrum_min+spectrum_width<256); int i; for(i=0; i &, int, int)) { assert(sfun!=NULL); assert(length>0); assert(repetitions>0); assert(spectrum_min<256); assert(spectrum_min+spectrum_width<256); autoarray test(length); int r; //cout<<"Dead time for every benchmark: "; cout.flush(); clock_t dead_clock=clock(); assert(dead_clock!=static_cast(-1)); RAND.setseed(321); for(r=0; r(-1)); dead_clock=current_clock-dead_clock; //const double dead_time=dead_clock/static_cast(CLOCKS_PER_SEC); //cout<(-1)); RAND.setseed(321); for(r=0; r(-1)); benchmark_clock=current_clock-benchmark_clock-dead_clock; const double benchmark_time=benchmark_clock/static_cast(CLOCKS_PER_SEC); cout<