/*
 * ===========================
 * VDK Visual Development Kit
 * Version 0.4
 * October 1998
 * ===========================
 *
 * Copyright (C) 1998, Mario Motta
 * Developed by Mario Motta <mmotta@guest.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-130
 */ 


#ifndef VDKHEAP_H
#define VDKHEAP_H

#include <vdk/container.h>

inline int parent(int i) { return ((i-1) >> 1); }
inline int left(int i) { return ((i << 1) + 1); }
inline int right(int i) { return ((i << 1) + 2); }
/*!
  \class VDKHeap
  \brief provide a templatized Heap

  \par Description
  VDKHeap<T> class has a value semantic, all objects are copied 
  from original values. 
  All managed type T objects should provide:
  \arg a default constructor: T::T()
  \arg a copy initializer: T::T(T& t) 
  \arg an assignement operator: T& T::operator=(T& t) 
  \arg an equality and less-than operators:
  \arg bool T::operator==(T& t)
  \arg bool T::operator<(T& t)
  \par Implementation notes
  I suggest to use typedef's like:
  \code
  typedef VDKHeap<someClass> SomeClassHeap;
  \endcode
 */
template <class T> class VDKHeap: public VDKContainer<T>
{
 public:
  /*!
    Constructor
    makes an empty heap
   */
  VDKHeap(): VDKContainer<T>(0) {}  
  /*!
    Constructor
    \param source an array of type T obejcts
    \param array size
  */
  VDKHeap(T* source, int size);
  /*!
    Destructor
   */
  virtual ~VDKHeap() {}
  /*!
    Sorts on nlog(n) time
   */
  void Sort(void);
protected:
  void Heapify(int i,int heapsize);
  void BuildHeap(void);
};

// make an heap copyng data from T type source vector
template <class T>
VDKHeap<T>::VDKHeap(T* source, int size): VDKContainer<T>(size) 
{
  for(int i = 0; i < size; i++)
    this->data[i] = source[i];
  BuildHeap();
}

// HEAPIFY
template <class T>
void VDKHeap<T>::Heapify(int i, int heapsize)
{
  int l = left(i), r = right(i), largest = i;
  if( (l < heapsize) && (this->data[l] > this->data[i])) largest = l;
  if( (r < heapsize) && (this->data[r] > this->data[largest])) largest = r;
  if(largest != i)
    {
      T temp = this->data[i];
      this->data[i] = this->data[largest];
      this->data[largest] = temp;
      Heapify(largest,heapsize);
    }
}

// BUILDHEAP
template <class T>
void VDKHeap<T>::BuildHeap(void)
{
  for (int i = (this->size()-1)/2 ; i >= 0; i--)	
    Heapify(i,this->size());
}

// HEAPSORT
template <class T>
void VDKHeap<T>::Sort(void)
{
  int heapsize = this->size();
  int i = heapsize-1;
  for(; i > 0; i--)
    {
      T temp = this->data[0];
      this->data[0] = this->data[i];
      this->data[i] = temp;
      heapsize--;
      Heapify(0,heapsize);
    }
}
#endif






