#include #include #include // for atoi #include "CPstring.h" #include "ctimer.h" #include "rando.h" #include "vector.h" // // skeleton program for comparing different sorting algorithms // this program provides a scaffolding for implementing and // timing different sort routines. // // Ideally all routines should have the same prototype: // // template void SortRoutine(Vector &, int) // // where the first parameter is an array to be sorted and // the second parameter is the number of elements of the array // // // author: Owen Astrachan (for cps100) // date: 3/17/93, revised and updated to C++ 10/26/93 // to incorporate template versions of sort routines // // revised 11/14/94 to include more sorts and clean up code // revised 10/15/95 to use vectors instead of arrays // revised 10/17/95 to use class SortBench // revised 11/28/95 to use ofstream varaible to record data // // SortBench -- constructor specifies a name for the sort, a sort function // and the name of an output file for data // use: SortBench selInt("select int",SelectSort,"selint.dat") // first parameter is a name for the sort (can be used // in generating output data), second parameter is a pointer // to a function that will sort a vector given the vector and // the number of elements as parameters, e.g., // // template Sort(Vector & a, int numElts); // // third parameter is name of output file that will be used // to store all timings (also echoed to screen). The file // facilitates the use of graphing programs to process all data // // TimeSort(Vector & a, int n) -- time the sort, // parameters are vector and number of elements in vector // vector is sorted, output is generated giving stats on sort // template class SortBench { public: SortBench(const string & name, // constructor void (*fptr)(Vector &, int), const string & filename); void TimeSort(Vector & a, int numElts); // time sort private: void (*myFuncPtr)(Vector &, int); // sorting function string myName; // name of sort ofstream myOutput; // name of output file }; template SortBench::SortBench(const string & name, void (*fptr)(Vector &, int), const string & filename) // // precondition: ftpr is a function that will sort Vector // postcondition: all fields initialized { myFuncPtr = fptr; myName = name; myOutput.open(filename); } template void SortBench::TimeSort(Vector & a, int numElts) // precondition: numElts = # of elements in vector a // postcondition: vector a is sorted, sort is timed, results // of timing generated and processed { CTimer timer; cout << myName << " " << numElts << " = "; timer.Start(); (*myFuncPtr)(a,numElts); timer.Stop(); cout << timer.ElapsedTime() << " seconds" << endl; myOutput << numElts << " " << timer.ElapsedTime() << endl; // write to datafile } const int MAX = 50001; // largest number of array elements const int CUTOFF = 20; // used in quick/merge sorts const int MIN_STR = 10; // minimum random string size const int MAX_STR = 15; // maximum random string size typedef int INT; template void Swap(Vector & v,int j, int k) // precondition: v[j] references value A, v[k] references value B // postcondition: v[k] references value B, v[k] references value A { Type temp = v[j]; v[j] = v[k]; v[k] = temp; } void RandLoad(Vector & a, int num) // postcondition: a is filled with num random string entries { int j,k; RandGen rnd; char buf[50]; for(k=0;k & a,int num,int range) // postcondition: a is an array of of num numbers // all numbers are in the range 0 to range - 1 { int k; RandGen rnd; for(k=0;k void PrintArray(Vector & a, int len) // precondition: Type has operator << defind // postcondition: n elements of array printed one per line { int k; for(k=0; k < len; k++) { cout << a[k] << endl; } } template void Insert(Vector & a ,int left,int right) // precondition: left <= right // postcondition: a[left] <= ... <= a[right] // // standard insertion sort between left/right // for use in small quick/merge cases as well { int k,loc; Type hold; for(k=left+1;k<=right;k++) { // shift elements to make room for a[k] hold = a[k]; // insert this element loc = k; // location for insertion while (left < loc && hold < a[loc-1]) { a[loc] = a[loc-1]; loc--; } a[loc] = hold; } } template void InsertSort(Vector & a, int size) // precondition: size = # of elements of a // postcondition: a is sorted // // uses insertion sort { Insert(a,0,size-1); } template void SelectSort(Vector & a, int size) // precondition: size = # of elements of a // postcondition: a is sorted // // standard selection sort { int j,k,min; for(j=0; j< size-1;j++) { min = j; for(k=j+1; k void BubbleSort(Vector & a, int n) // precondition: n = # of elements in a // postcondition: a is sorted // note: this is a dog of a sort { int j,k; for(j=n-1; j > 0; j--) { // find largest element in 0..k, move to a[j] for(k=0; k < j; k++) { if (a[k+1] < a[k]) { Swap(a,k,k+1); } } } } template void ShellSort(Vector & a, int n) // precondition: n = # elements in a // postcondition: a is sorted // // shell sort using Hibbard increments, see Weiss { int h,j,k,loc,increment; Type hold,temp; for(h=1; h <= n/2; h <<= 1 ) { // found power of 2 closest to n/2 } h--; // went past n/2 in loop guard for( ; h > 0; h /= 2) { // insertion sort using jumps of 'size' h for(k=h; k < n; k++) { hold = a[k]; loc = k; while (h <= loc && hold < a[loc-h]){ a[loc] = a[loc-h]; loc -= h; } a[loc] = hold; } } } template void Merge(Vector & a, int left,int mid,int right) // precondition: a sorted from a[left] ... a[mid] and from // a[mid+1] to a[right] // extra storage passed in // postcondition: a sorted from a[left] ... a[right] { static Vector b(MAX); // aux storage int lk=left; // a's left index int rk = mid+1; // a's right index int bk = left; // b's index while (lk <= mid && rk <= right) // both parts non-empty? { if (a[lk] <= a[rk]) b[bk++] = a[lk++]; else b[bk++] = a[rk++]; } // finish any leftovers in a (only one of loops below executes) while (lk <= mid) b[bk++] = a[lk++]; while(rk <= right) b[bk++] = a[rk++]; // copy b back to a for(lk=left,rk=left;lk<=right;lk++) a[lk] = b[rk++]; } template void DoMerge(Vector & a, int left,int right) // postcondition: a[left] <= ... <= a[right] { int mid = (left+right)/2; if (right - left > CUTOFF) { DoMerge(a,left,mid); DoMerge(a,mid+1,right); Merge(a,left,mid,right); } else { Insert(a,left,right); } } template void MergeSort(Vector & a,int n) { DoMerge(a,0,n-1); } template int Median(Vector & a,int first,int last) // postcondition: returns index of median element of // a[first],a[last],a[mid], mid = (first+last)/2 { int mid=(first+last)/2; if (a[mid] > a[first]) { if (a[last] > a[mid]) return mid; else if (a[last] > a[first]) return last; else return first; } else { if (a[last] > a[first]) return first; else if (a[mid] > a[last]) return mid; else return last; } } template int Pivot(Vector & a,int first,int last) // postcondition: returns piv such that // first <= k <= piv, a[k] <= a[piv] // piv < k <= last, a[piv] < a[k] // standard Bently/ola pivot routine { int k,p=first; Type piv; Swap(a,first,Median(a,first,last)); piv = a[first]; for(k=first+1;k<=last;k++) { if (a[k] <= piv) { p++; Swap(a,k,p); } } Swap(a,p,first); return p; } template void Quick(Vector & a,int first,int last) // postcondition: a[first] <= ... <= a[list] { int piv; if (last - first > CUTOFF) { piv = Pivot(a,first,last); Quick(a,first,piv-1); Quick(a,piv+1,last); } else { Insert(a,first,last); } } template void QuickSort(Vector & a, int size) // precondition: size = # of elements of a // postcondition: a is sorted { Quick(a,0,size - 1); } main(int argc, char *argv[]) { Vector aInt(MAX); // define storage for arrays Vector storeInt(MAX); Vector aString(MAX); Vector storeString(MAX); SortBench selectInt("select int",SelectSort,"selectint.data"); SortBench selectString("select string",SelectSort, "selectstr.data"); int j,k,num; int radix = 100000; long before,after; if (argc > 1){ // first arg is # radix radix = atoi(argv[1]); // (all #'s less than radix) } for(num = 500; num <= 1000; num += 500) { RandLoad(storeInt,num,radix); // create random vectors RandLoad(storeString,num); // copy stored vectors into vectors that will be sorted aInt = storeInt; aString = storeString; // now sort the vectors selectInt.TimeSort(aInt,num); selectString.TimeSort(aString,num); } }