
//  Program:  merge sort
//  Author:   Chuck Stewart
//
//  Purpose:  A program to demonstrate the recursive merge sort technique.


#include <iostream>
#include <vector>
using namespace std;

//  Non-recursive function to merge two sorted intervals of a vector,
//  using "scratch" as temporary copying space.  The intervals are
//  subscript locations low..mid and mid+1..high

template <class T>
void
merge( int low, int mid, int high, 
       vector<T>& values,
       vector<T>& scratch )
{
  cout << "merge:  low = " << low << ", mid = " << mid << ", high = "
       << high << endl;
  int i=low, j=mid+1, k=low;

  // while one interval is not exhausted
  while(  i<=mid && j<=high )
    {
      if ( values[i] < values[j] )
	{
	  scratch[k] = values[i];
	  ++k; ++i;
	}
      else 
	{
	  scratch[k] = values[j];
	  ++k; ++j;
	}
    }
  for ( ; i<=mid; ++i, ++k ) scratch[k] = values[i];
  for ( ; j<=high; ++j, ++k ) scratch[k] = values[j];
  for ( k=low; k<=high; ++k ) values[k] = scratch[k];
}


//  Here's the actual merge sort function.  It splits the vector in
//  half, recursively sorts each half, and then merges the two sorted
//  halves into a single sorted interval.
      
template <class T>
void
mergesort( int low, int high, 
           vector<T>& values,
           vector<T>& scratch )
{
  cout << "mergesort:  low = " << low << ", high = " << high << endl;
  if ( low >= high )  //  intervals of size 0 or 1 are already sorted!
    return;

  int  mid = (low + high) / 2;
  mergesort( low, mid, values, scratch );
  mergesort( mid+1, high, values, scratch );
  merge( low, mid, high, values, scratch );
}


//  The driver function for mergesort.  It defines a scratch vector
//  for temporary copies.  It passes this vector along with the region
//  to be sorted to the recursive mergesort function.

template <class T>
void
mergesort( vector<T>& values )
{
  vector<T> scratch( values.size() );
  mergesort( 0, int(values.size()-1), values, scratch );
}


int 
main()
{
  // vector<double> pts(20);
  vector<double> pts(7);
  pts[0] = -45.0;  pts[1] =   89.0;  pts[2] =    34.7;  pts[3] =   21.1;
  pts[4] =   5.0;  pts[5] =  -19.0;  pts[6] =  -100.3;  // pts[7] =    3.8;
  // pts[8] =  77.1;  pts[9] =   13.6;  pts[10] = -221.4;  pts[11] = 121.5;
  //  pts[12] = 25.9;  pts[13] = 123.2;  pts[14] =   66.6;  pts[15] =   8.3;
  // pts[16] = 55.5;  pts[17] = 898.1;  pts[18] =   42.3;  pts[19] =  77.7;

  mergesort( pts );

  for ( unsigned int i=0; i<pts.size(); ++i )
    cout << i << ": " << pts[i] << endl;
}
  

