/* Quicksort algorithm sorts array of objects.  The type of the 
objects must accept the comparison operators < and ==  (for example
the number types -- but note that these operators can be defined for 
other types as we will see in chapter 8.)   -bds 11/98
*/
#include <stdlib.h> // for rand()
extern int swaps;
extern int comparisons;

// sort array in place.
// class Comparable must support comparisons '<' and '=='.

template <class Comparable>
Comparable* twoPiles( Comparable* first, Comparable* last, Comparable key );

void quickSort( int* first, int* last ) 
{
  if ( last - first <= 0 ) return; // a one element array is sorted!

  int* keyLocation = first + rand()%(last - first + 1);
  int* restingPlace = twoPiles(first, last, *keyLocation);

  quickSort( first, restingPlace - 1 );

  quickSort( restingPlace + 1, last );
}

template <class Comparable>
Comparable* twoPiles( Comparable* first, Comparable* last, Comparable key ) 
// We assume first <= last and that *first thru *last are 
// values of class Comparable and that the key value is among them, 
// We permute the values in the range *first to *last and 
// we return a pointer p such that *p = key and 
// *first thru *(p-1) are <= key and 
// *(p+1) thru *last are >= key.
{
  if ( first >= last ) return first;
  Comparable* fPP = first; // fPP stands for first Potential Problem
  Comparable* lPP = last; // lPP stands for last Potential Problem

  // find first item out of place
  while ( *fPP < key ) 
    comparisons++, fPP++;
  // assert *first thru *(fPP-1) are less than key and 
  // *fPP is greater than or equal to key.

  // find last item out of place
  while ( key < *lPP ) 
    comparisons++, lPP--;
  // assert *lPP+1 thru *last are greater than key and 
  // *lPP is less than or equal to key.

  // make sure of some progress toward finishing
  swap( fPP, lPP );
  // assert *fPP <= key and *lPP >= key.
  if ( *fPP < key ) 
    comparisons++, fPP++;
  if ( key < *lPP || *fPP == key )
    comparisons++, lPP--;

  // continue process 
  return twoPiles( fPP, lPP, key);
}

template< class T >
void swap( T* a, T* b ) {
  swaps++;
  T temp = *a;
  *a = *b;
  *b = temp;
}

