// L-32 MCS 360 Fri 10 Apr 2020 : quicksort

/* This basic version of quicksort follows closely the original
   recursive formulation of the algorithm. */

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>
using namespace std;

vector< pair<int,char> > random_vector ( int n );
// returns a vector of n random 2-digit numbers
// associated with lower case letters

void write_vector ( vector< pair<int,char> > v );
// writes the vector v

void vanilla_quicksort 
 ( vector< pair<int,char> >& v, int k );
// applies quicksort to the vector v, the parameter k
// keeps track of the levels of recursion, initialize with 0

int main()
{
   cout << "give n : ";
   int n; cin >> n;

   srand(time(0));
   vector< pair<int,char> > v = random_vector(n);
   cout << n << " random items : ";
   write_vector(v); cout << endl;

   vanilla_quicksort(v,0);

   cout << "the sorted vector : ";
   write_vector(v); cout << endl;

   return 0;
}

vector< pair<int,char> > random_vector ( int n )
{
   vector< pair<int,char> > v;

   for(int i=0; i<n; i++)
   {
      pair<int,char> p;
      p.first = 10 + (rand() % 90);
      p.second = 'a' + rand() % 26;
      v.push_back(p);
   }

   return v;
}

void write_vector ( vector< pair<int,char> > v )
{
   for(int i=0; i<v.size(); i++)
      cout << "(" << v[i].first
           << "," << v[i].second
           << ")";
}

void vanilla_quicksort 
 ( vector< pair<int,char> >& v, int k )
{
   for(int i=0; i<k; i++) cout << "  ";
   write_vector(v); cout << endl;
   
   if(v.size() > 1)
   {
      vector< pair<int,char> > a,b;
      pair<int,char> pivot = v[0];

      for(int i=1; i<v.size(); i++)
         if(v[i].first <= pivot.first)
            a.push_back(v[i]);
         else if(v[i].first > pivot.first)
            b.push_back(v[i]);

      if(a.size() > 0) vanilla_quicksort(a,k+1);
      if(b.size() > 0) vanilla_quicksort(b,k+1);

      for(int i=0; i<a.size(); i++) v[i] = a[i];
      v[a.size()] = pivot;
      for(int i=0; i<b.size(); i++) v[i+a.size()+1] = b[i];
   }
}
