#ifndef _STACK_HPP_
#define _STACK_HPP_
#include <iostream>


template <class T>
class Stack
{
private:
  T *_v;
  int _len = 10;
  int _used = 0;

public:
  Stack()
  {
    _v = new T[_len];
  }

  void push(T const &elem)
  {
    _v[_used++] = elem;
    expand();
  }

  T pop() { return !_used ? NULL : _v[--_used]; }

  T top() const { return !_used ? NULL : _v[_used - 1]; }

  bool empty() { return _used ? false : true; }

  int depth() { return _used; };

protected:
  void expand()
  {
    if (((double)_used / (double)_len) <= 0.75)
      return;
    _len = _len * 2;
    T *p = new T[_len];

    for (int i = 0; i <= _used; i++)
      p[i] = _v[i];

    delete[] _v;
    _v = p;
  }

  void shrink()
  {
    if (((double)_used / (double)_len) >= 0.25)
      return;

    _len = _len >> 1;
    T *p = new T[_len];

    for (int i = 0; i <= _used; i++)
      p[i] = _v[i];

    delete[] _v;
    _v = p;
  }
};
#endif