
#include <iostream>
#include <time.h>
#include <fstream>

using namespace std;

#define MAX_LIST_SIZE 500000

////////////////BEGIN SORTS CLASS////////////
/*
Class Name:  sorts
Class Description:  a class with implementations of various sorting algorithms
*/

/*remove comments (and then comment out the lines immediately following the
  commented out line) in order to use this as a tamplate class that can
  sort an array of any comparable data type*/

//template <class dataType>
class sorts
{
public:
	sorts();

	//sorts(dataType* first);
	sorts(int* first);

	void quickSort(size_t index, size_t maxIndex);
	void heapSort(size_t length);
	void mergeSort(size_t lowerIndex, size_t upperIndex);
	void bubbleSort(size_t length);
	void insertionSort(size_t length);
	void selectionSort(size_t length);

	void print(size_t length);

	//void setFirstEntry(dataType* first);
	void setFirstEntry(int* first);

	//dataType* getFirstEntry();
	int* getFirstEntry();

private:
	//dataType* firstEntry;  //pointer to the first array element
	int* firstEntry;  //pointer to the first array element

};

/*
Function Name:  sorts::sorts
Description:  default constructor for the sorts class
Parameters:  None
Return values:  None
*/
//template <class dataType>
//sorts<dataType>::sorts()
sorts::sorts()
{
	firstEntry = NULL;
}

/*
Function Name:  sorts::sorts
Description:  constructor for the sorts class
Parameters:  first (dataType*) : a pointer to the first array element (&array[0])
Return values:  None
*/
//template <class dataType>
//sorts<dataType>::sorts(dataType* first)
sorts::sorts(int* first)
{
	firstEntry = first;
}

/*
Function Name:  sorts::setFirstEntry
Description:  sets firstEntry to point to the first item in an array
Parameters:  first (dataType*) : a pointer to the first array element (&array[0])
Return values:  None
*/
//template <class dataType>
//void sorts<dataType>::setFirstEntry(dataType* first)
void sorts::setFirstEntry(int* first)
{
	firstEntry = first;
}

/*
Function Name:  sorts::getFirstEntry
Description:  returns a pointer to the first object in the array (in case the
              calling function suffers a seizure or something and forgets it)
Parameters:  None
Return values:  dataType* (first) : a pointer to the first element of the array
*/
//template <class dataType>
//dataType* sorts<dataType>::getFirstEntry()
int* sorts::getFirstEntry()
{
	return firstEntry;
}

/*
Function Name:  sorts::print
Description:  prints the contents of the list
Parameters:  length (size_t) : specifies the number of entries in the list
Return values:  None
*/
//template <class dataType>
//void sorts<dataType>::print(size_t length)
void sorts::print(size_t length)
{
	if (firstEntry != NULL)
	{
		for (int count = 0; count < length; count++)
		{
			cout << firstEntry[count] <<endl;
		}
	}
}

/*
Function Name:  sorts::quickSort
Description:  function to sort a list of numbers using the Quick Sort algorithm
Parameters:  index (int) : the index of the first array element
	         maxIndex (int) : the index of the last array element
Return values:  None
*/
//template <class dataType>
//void sorts<dataType>::quickSort(size_t index, size_t maxIndex)
void sorts::quickSort(size_t index, size_t maxIndex)
{
	//IMPLEMENT ME
}

/*
Function Name:  sorts::heapSort
Description: function to sort a list of numbers using the Heap Sort algorithm
Parameters:  length (int) : total number of elements in the array
Return values:  None
*/
//template <class dataType>
//void sorts<dataType>::heapSort(size_t length)
void sorts::heapSort(size_t length)
{
	//IMPLEMENT ME
}

/*
Function Name:  sorts::mergeSort
Description:  function to sort a list of numbers using the Merge Sort algorithm
Parameters:  lowerIndex (int) : the index of the first array element
	         upperIndex (int) : the index of the last array element
Return values:  None
*/
//template <class dataType>
//void sorts<dataType>::mergeSort(size_t lowerIndex, size_t upperIndex)
void sorts::mergeSort(size_t lowerIndex, size_t upperIndex)
{
	//IMPLEMENT ME
}

/*
Function Name:  sorts::insertionSort
Description:  function to sort a list of number using the Insertion Sort algorithm
Parameters:  length (int) : the number of elements in the list
Return values:  None
*/
//template <class dataType>
//void sorts<dataType>::insertionSort(size_t length)
void sorts::insertionSort(size_t length)
{
	//IMPLEMENT ME
}

/*
Function Name:  sorts::bubbleSort
Description:  function to sort a list of number using the Bubble Sort algorithm
Parameters:  length (int) : the number of elements in the list
Return values:  None
*/
//template <class dataType>
//void sorts<dataType>::bubbleSort(size_t length)
void sorts::bubbleSort(size_t length)
{
	//IMPLEMENT ME
}

/*
Function Name:  sorts::selectionSort
Description:  function to sort a list of number using the Selection Sort algorithm
Parameters:  length (int) : the number of elements in the list
Return values:  None
*/
//template <class dataType>
//void sorts<dataType>::selectionSort(size_t length)
void sorts::selectionSort(size_t length)
{
	//IMPLEMENT ME
}
////////////////END SORTS CLASS/////////


void instructions();
int load(int* list, size_t maxIndex, ifstream& infile);

int main ()
{
	instructions();

	sorts numberSort;
    ifstream input;
    int numbers[MAX_LIST_SIZE];
    int arraySize;
	clock_t time1, time2;  /*Timekeeping variables*/

	//open the input file
	input.open("numbers.txt");

	//load the data to our array
	cout << "Loading data from file 'numbers.txt'..."<<endl;
	arraySize = load(numbers, MAX_LIST_SIZE, input);
	cout << arraySize << " entries loaded successfully" <<endl<<endl;

	numberSort.setFirstEntry(&numbers[0]);

	//call the first sorting algorithm, and report the time it takes
	cout << "Calling first algorithm now..."<<endl;
	time1 = clock();
	//numberSort.bubbleSort(arraySize);
	time2 = clock();
	cout <<"The sorting process took "<<(float)(time2 - time1) / (float)CLOCKS_PER_SEC
	     <<" seconds for a list size of "<<arraySize<<"."<<endl<<endl;

	//reset and reopen the input file
	input.seekg(0);
	input.clear();
	input.close();
	input.open("numbers.txt");

	//reload the array
	cout << "Reloading data from file 'numbers.txt'..."<<endl;
	arraySize = load(numbers, MAX_LIST_SIZE, input);
	cout << "Data loaded successfully" <<endl <<endl;

	//call the second algorithm, and report the time it takes
	cout << "Calling second algorithm now..."<<endl;
	time1 = clock();
	//numberSort.heapSort(arraySize);
	time2 = clock();
	cout <<"The sorting process took "<<(float)(time2 - time1) / (float)CLOCKS_PER_SEC

	     <<" seconds for a list size of "<<arraySize<<"."<<endl<<endl;

	input.seekg(0);
	input.clear();
	input.close();

    return 0;
}


/*
Function Name:  load
Description:  populates an array with data contained in an input file
Parameters:  list (int*) : pointer to the first element in the array to populate
			 maxIndex (size_t) : the capacity of the list, so that we do not write
			 					 past the end of the array
			 infile (ifstream) : the file to read the data from
Return values:  int : the number of elements loaded into the list
*/
int load(int* list, size_t maxIndex, ifstream& infile)
{
	int arraySize = 0;
	for(int place = 0; ((place < maxIndex) && (!infile.eof()));place++)
	{
		infile >> list[place];
		if(!infile.eof())
		{
			arraySize++;
		}
	}

	return arraySize;
}

/*
Function Name:  instructions
Description:  A function to output instructions for the user
Parameters:  None
Return values:  None
*/
void instructions()
{
    cout<<"You should implement the 'instructions()' function"<<endl
        <<endl<<endl;
}

