TDArray

// TDArrayMain.cpp

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

#include "TDArray.h"
#include "TDArray.cpp"

int main(int argc, char *argv[])
{
  TDArray<int> arr1, arr2(5);
  cout << "arr1.length: " << arr1.Length() << "; arr2.length: " << arr2.Length() << endl;
  if ((argc>1) && (atoi(argv[1]) == 1))	// testing level 1
    {
      cout << "attempt access arr1[0]," << endl;
      cout << arr1[0];
    }
  cout << "arr2: ";
  for (int i=0; i<arr2.Length(); i++)
    {
      cout << arr2[i] << " ";
    }
  cout << endl;

  arr2[0] = 1, arr2[1] = 6, arr2[2] = 9, arr2[3] = 3, arr2[4] = 7;
  cout << "After filling, arr2: ";
  for (int i=0; i<arr2.Length(); i++)
    {
      cout << arr2[i] << " ";
    }
  cout << endl;

  TDArray<int> arr3 = arr2;
  cout << "arr3 = arr2, arr3: ";
  for (int i=0; i<arr3.Length(); i++)
    {
      cout << arr3[i] << " ";
    }
  cout << endl;

  arr1 = arr3(1, 4);
  cout << "arr1 = arr3(1, 4), arr1: ";
  for (int i=0; i<arr1.Length(); i++)
    {
      cout << arr1[i] << " ";
    }
  cout << endl;

  TDArray<int> arr4 = arr3 & arr1;
  cout << "arr4 = arr3 & arr1, arr4: ";
  for (int i=0; i<arr4.Length(); i++)
    {
      cout << arr4[i] << " ";
    }
  cout << endl;

  arr3.Delete(0);
  cout << "arr3.Delete(0), arr3: ";
  for (int i=0; i<arr3.Length(); i++)
    {
      cout << arr3[i] << " ";
    }
  cout << endl;

  arr3.Delete(3);
  cout << "arr3.Delete(3), arr3: ";
  for (int i=0; i<arr3.Length(); i++)
    {
      cout << arr3[i] << " ";
    }
  cout << endl;

  arr3.Insert(7, 3);
  cout << "arr3.Insert(7, 3), arr3: ";
  for (int i=0; i<arr3.Length(); i++)
    {
      cout << arr3[i] << " ";
    }
  cout << endl;

  arr3.Insert(1, 0);
  cout << "arr3.Insert(1, 0), arr3: ";
  for (int i=0; i<arr3.Length(); i++)
    {
      cout << arr3[i] << " ";
    }
  cout << endl;

  cout << "arr4.LSearch(9) = " << arr4.LSearch(9) << endl;
  cout << "arr4.IndexOfMin(3, 6) = " << arr4.IndexOfMin(3, 6) << endl;
  cout << "arr4.IndexOfMin() = " << arr4.IndexOfMin() << endl;

  arr3.SSort();
  cout << "arr3.SSort(), arr3: ";
  for (int i=0; i<arr3.Length(); i++)
    {
      cout << arr3[i] << " ";
    }
  cout << endl;

  arr4.QSort();
  cout << "arr4.QSort(), arr4: ";
  for (int i=0; i<arr4.Length(); i++)
    {
      cout << arr4[i] << " ";
    }
  cout << endl;
  cout << "arr4.BSearch(9) = " << arr4.BSearch(9) << endl;

  return 0;
}
// TDArray.h
#ifndef TDARRAY_
#define TDARRAY_

#include <cstdlib>		// for size_t

template <typename ArrayElem>
class TDArray
{
  // helper function for recursive version of BSearch
  const ArrayElem* BinarySearch(const ArrayElem& elem, const ArrayElem *array, size_t length) const;
  // helper function for QSort
  unsigned int Split(unsigned int low, unsigned int high);
  void QuickSort(unsigned int low, unsigned int high);
protected:
  ArrayElem *array_;
  size_t length_;
public:
  TDArray(size_t length=0);
  TDArray(const TDArray& tdArray);
  ~TDArray(void);

  const ArrayElem& operator[](unsigned int i) const;
  ArrayElem& operator[](unsigned int i);
  size_t Length(void) const { return length_; }

  TDArray& operator=(const TDArray& tdArray);
  TDArray operator()(unsigned int first, unsigned int last) const;
  TDArray operator&(const TDArray& tdArray) const;

  bool Insert(const ArrayElem& elem, unsigned int pos);
  bool Delete(unsigned int pos);

  int LSearch(const ArrayElem& elem) const;
  int BSearch(const ArrayElem& elem) const;

  // helper function for SSort, but also useful for it own
  unsigned int IndexOfMin(unsigned int first, unsigned int last) const;
  unsigned int IndexOfMin() const { return IndexOfMin(0, length_-1); }
  void Swap(unsigned int i1, unsigned int i2)
    {
      ArrayElem temp = array_[i1];
      array_[i1] = array_[i2];
      array_[i2] = temp;
    }
  void SSort(void);
  void QSort(void);
};

#endif
// TDArray.cpp

#include <cstdlib>		// for exit()
#include <iostream>
using namespace std;

#include "TDArray.h"

template <typename ArrayElem>
TDArray<ArrayElem>::TDArray(size_t length)
{
  length_ = length;
  if (length_ == 0)
    array_ = NULL;
  else
    {
      array_ = new ArrayElem[length_];
      if (array_ == NULL)
	{
	  cerr << "\n*** unable allocate TDArray in call to TDArray constructor\n";
	  exit(-1);
	}
    }
}

template <typename ArrayElem>
TDArray<ArrayElem>::TDArray(const TDArray& tdArray)
{
  length_ = tdArray.length_;
  if (tdArray.array_ == NULL)
    array_ = NULL;
  else
    {
      array_ = new ArrayElem[length_];
      if (array_ == NULL)
	{
	  cerr << "\n*** unable allocate TDArray in call to TDArray copy constructor\n";
	  exit(-1);
	}
      else
	{
	  for (int i=0; i<length_; i++)
	    array_[i] = tdArray.array_[i];
	}
    }
}

template <typename ArrayElem>
TDArray<ArrayElem>::~TDArray(void)
{
  length_ = 0;
  if (array_ != NULL)
    {
      delete []array_;
      array_ = NULL;
    }
}

template <typename ArrayElem>
const ArrayElem& TDArray<ArrayElem>::operator[](unsigned int i) const
{
  if (i < length_)
    return array_[i];
  else
    {
      cerr << "\n*** attempt access past end of TDArray in call to operator[]\n";
      exit(-1);
    }
}

template <typename ArrayElem>
ArrayElem& TDArray<ArrayElem>::operator[](unsigned int i)
{
  if (i < length_)
    return array_[i];
  else
    {
      cerr << "\n*** attempt access past end of TDArray in call to operator[]\n";
      exit(-1);
    }
}

template <typename ArrayElem>
TDArray<ArrayElem>& TDArray<ArrayElem>::operator=(const TDArray& tdArray)
{
  if (this != &tdArray)		// self-test
    {
      if (length_ != tdArray.length_)
	{
	  length_ = tdArray.length_;
	  if (array_ != NULL)
	    delete []array_;
	  if (tdArray.array_ == NULL)
	    array_ = NULL;
	  else
	    {
	      array_ = new ArrayElem[length_];
	      if (array_ == NULL)
		{
		  cerr << "\n*** unable reallocate TDArray in call to operator=\n";
		  exit(-1);
		}
	    }
	}
      if (array_ != NULL)
	{
	  for (int i=0; i<length_; i++)
	    array_[i] = tdArray.array_[i];
	}
    }
  return *this;
}

template <typename ArrayElem>
TDArray<ArrayElem> TDArray<ArrayElem>::operator()(unsigned int first, unsigned int last) const
{
  if (last >= length_)
    {
      cerr << "\n*** last too big in call to operator()\n";
      last = length_ - 1;
    }
  if (first > last)
    {
      cerr << "\n*** first pass last in call to operator()\n";
      exit(-1);
    }
  TDArray tdArray;
  tdArray.length_ = last - first + 1;
  tdArray.array_ = new ArrayElem[tdArray.length_];
  if (tdArray.array_ == NULL)
    {
      cerr << "\n*** unable allocate TDArray in call to operator()\n";
      exit(-1);
    }
  else
    {
      for (int i=0, j=first; i<length_; i++, j++)
	tdArray.array_[i] = array_[j];
    }
  return tdArray;
}

template <typename ArrayElem>
TDArray<ArrayElem> TDArray<ArrayElem>::operator&(const TDArray& tdArray) const
{
  TDArray tdArray2;
  if (array_ != NULL && tdArray.array_ != NULL)
    {
      tdArray2.length_ =length_ + tdArray.length_;
      tdArray2.array_ = new ArrayElem[tdArray2.length_];
      if (tdArray2.array_ == NULL)
	{
	  cerr << "\n*** unable allocate TDArray in call to operator&\n";
	  exit(-1);
	}
      else
	{
	  int i, j;
	  for (i=0; i<length_; i++)
	    tdArray2.array_[i] = array_[i];
	  for (j=0; j<tdArray.length_; i++, j++)
	    tdArray2.array_[i] = tdArray.array_[j];
	}
      return tdArray2;
    }
  else if (array_ != NULL)
    return *this;
  else				// if (tdArray.array_ != NULL)
    return tdArray;
}

template <typename ArrayElem>
bool TDArray<ArrayElem>::Insert(const ArrayElem& elem, unsigned int pos)
{
  if (pos > length_)
    {
      cerr << "\n*** attempt insert past end of TDArray\n";
      pos = length_;
    }
  ArrayElem *temp = new ArrayElem[length_+1];
  if (temp == NULL)
    {
      cerr<<"\n*** unable reallocate TDArray in call to Insert\n";
      return false;
    }
  else
    {
      int i;
      for (i=length_; i>pos; i--)
	{
	  temp[i] = array_[i-1];
	}
      temp[i] = elem;
      for (i--; i>=0; i--)
	{
	  temp[i] = array_[i];
	}
      length_++;
      if (array_ != NULL)
	delete []array_;
      array_ = temp;
    }
  return true;
}

template <typename ArrayElem>
bool TDArray<ArrayElem>::Delete(unsigned int pos)
{
  if (pos >= length_)
    {
      cerr << "\n*** last too big in call to Delete\n";
      pos = length_ - 1;
    }
  ArrayElem *temp = new ArrayElem[length_-1];
  if (temp == NULL)
    {
      cerr << "\n*** unable reallocate TDArray in call to Delete\n";
      return false;
    }
  else
    {
      int i;
      for (i=0; i<pos; i++)
	temp[i] = array_[i];
      for (; i<length_; i++)
	temp[i] = array_[i+1];
      length_--;
      if (array_ != NULL)
	delete []array_;
      array_ = temp;
    }
  return true;
}

template <typename ArrayElem>
int TDArray<ArrayElem>::LSearch(const ArrayElem& elem) const
{
  for (int i=0; i<length_; i++)
    {
      if (array_[i] == elem)
	return i;
    }
  return -1;
}

template <typename ArrayElem>
int TDArray<ArrayElem>::BSearch(const ArrayElem& elem) const
{
  int first=0, last = length_-1, mid;
  while (last >= first)
    {
      mid = (first+last) / 2;
      if (array_[mid] == elem)
	return mid;
      else if (array_[mid] > elem)
	last = mid - 1;
      else
	first = mid + 1;
    }
  return -1;
}

/* Recursive version */
/*
template <typename ArrayElem>
int TDArray<ArrayElem>::BSearch(const ArrayElem& elem) const
{
  const ArrayElem *temp = BinarySearch(elem, array_, length_);
  if (temp == NULL)
    return -1;
  else
    return (temp-array_);
}
*/

template <typename ArrayElem>
const ArrayElem* TDArray<ArrayElem>::BinarySearch(const ArrayElem& elem, const ArrayElem *array, size_t length) const
{
  int mid = length / 2;
  if (length == 0)
    return NULL;
  else if (array[mid] == elem)
    return (&array[mid]);
  else if (array[mid] > elem)
    return BinarySearch(elem, array, mid);
  else
    {
      if (length%2 == 0)
	return BinarySearch(elem, array+mid+1, length-mid-1);
      else
	return BinarySearch(elem, array+mid+1, length-mid);
    }
}

template <typename ArrayElem>
unsigned int TDArray<ArrayElem>::IndexOfMin(unsigned int first, unsigned int last) const
{
  if (last >= length_)
    {
      cerr << "\n*** last too big in call to IndexOfMin\n";
      last = length_ - 1;
    }
  if (first > last)
    {
      cerr << "\n*** first pass last in call IndexOfMin\n";
      exit(-1);
    }

  unsigned int minPos = first;
  for (int i=first+1; i<=last; i++)
    {
      if (array_[i] < array_[minPos])
	minPos = i;
    }
  return minPos;
}

template <typename ArrayElem>
void TDArray<ArrayElem>::SSort(void)
{
  unsigned int minPos;
  for (int i=0; i<length_; i++)
    {
      minPos = IndexOfMin(i, length_-1);
      if (minPos != i)
	Swap(i, minPos);
    }
}

template <typename ArrayElem>
unsigned int TDArray<ArrayElem>::Split(unsigned int low, unsigned int high)
{
  int left = low, right = high;
  ArrayElem pivot = array_[low];
  while (left < right)
    {
      while ((right>0) && (array_[right] > pivot))
	right--;
      while ((left<right) && (array_[left] <= pivot))
	left++;
      if (left < right)
	Swap(left, right);
    }
  if (right != low)
    {
      array_[low] = array_[right];
      array_[right] = pivot;
    }
  return right;
}
template <typename ArrayElem>
void TDArray<ArrayElem>::QuickSort(unsigned int low, unsigned int high)
{
  if (low < high)		// has 2 more items
    {
      unsigned int mid = Split(low, high);
      if (mid > 0)
	QuickSort(low, mid-1);
      QuickSort(mid+1, high);
    }
}
template <typename ArrayElem>
void TDArray<ArrayElem>::QSort(void)
{
  if (length_ > 1)
    QuickSort(0, length_-1);
}
Index