// L-31 MCS 360 Wed 3 Nov 2010 : heap_sort

/* The code below illustrates a heap sort,
   using the code of Lecture 26 on vectors of pairs. */

#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

int max_child ( vector< pair<int,char> >&v, int bottom, int p );
// returns -1 if no child, or otherwise index of largest child

void swap_from_top ( vector< pair<int,char> >&v, int bottom, int p );
// swaps the element at p with its largest child
// if that child has value larger than the parent

void remove ( vector< pair<int,char> >& v, int& bottom );
// removes the bottom element from the heap

void swap_from_bottom ( vector< pair<int,char> >& v, int p );
// if current element is larger than parent,
// then swaps current element at p to the top

void insert ( vector< pair<int,char> >& v, int& bottom, pair<int,char> p );
// insert the element p into the heap v

vector< pair<int,char> > vanilla_heap_sort ( vector< pair<int,char> >& v );
// applies heap sort to the vector v

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;

   vector< pair<int,char> > w = vanilla_heap_sort(v);

   cout << "the sorted vector : ";
   write_vector(w); 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
           << ")";
}

int max_child ( vector< pair<int,char> >&v, int bottom, int p )
{
   if(bottom <= p)
      return -1;
   else
   {
      int left = 2*p+1;
      int right = 2*p+2;

      if(left > bottom)
         return -1;
      else
      {
         if(right > bottom)
            return left;
         else
            return (v[left].first > v[right].first) ? left : right;
      }
   }
}

void swap_from_top ( vector< pair<int,char> >& v, int bottom, int p )
{
   if(bottom == -1) return;
   int c = max_child(v,bottom,p);
   if(c == -1) return;        

   if(v[c].first > v[p].first)
   {
      pair<int,char> t = v[p];
      v[p] = v[c]; v[c] = t;
      swap_from_top(v,bottom,c);
   }
}

void remove ( vector< pair<int,char> >& v, int& bottom )
{
   if(bottom == 0) 
      bottom--;
   else
   {
      v[0] = v[bottom--];
      swap_from_top(v,bottom,0);
   }
   v.pop_back();
}

void swap_from_bottom ( vector< pair<int,char> >& v, int p )
{
   if(p == 0) return;
   int parent = (p-1)/2;
   if(v[parent].first < v[p].first)
   {
      pair<int,char> t = v[p];
      v[p] = v[parent];
      v[parent] = t;
      swap_from_bottom(v,parent);
   }
}

void insert ( vector< pair<int,char> >& v, int& bottom, pair<int,char> p )
{
   v.push_back(p);
   bottom++;
   swap_from_bottom(v,bottom);
}

vector< pair<int,char> > vanilla_heap_sort ( vector< pair<int,char> >& v )
{
   vector< pair<int,char> > h,w;
   int bottom = -1;

   for(int i=0; i<v.size(); i++) 
   {
      insert(h,bottom,v[i]);
      cout << "insert i=" << i << " : ";
      write_vector(h); cout << endl;
   }

   for(int i=0; i<v.size(); i++)
   {
      w.insert(w.begin(),h[0]);
      remove(h,bottom);
      cout << "remove i=" << i << " : ";
      write_vector(h); cout << endl;
   }
   return w;
}

