| 1 | /*! |
|---|
| 2 | * \file |
|---|
| 3 | * \brief Stack class (container) |
|---|
| 4 | * \author Thomas Eriksson |
|---|
| 5 | * |
|---|
| 6 | * ------------------------------------------------------------------------- |
|---|
| 7 | * |
|---|
| 8 | * IT++ - C++ library of mathematical, signal processing, speech processing, |
|---|
| 9 | * and communications classes and functions |
|---|
| 10 | * |
|---|
| 11 | * Copyright (C) 1995-2007 (see AUTHORS file for a list of contributors) |
|---|
| 12 | * |
|---|
| 13 | * This program is free software; you can redistribute it and/or modify |
|---|
| 14 | * it under the terms of the GNU General Public License as published by |
|---|
| 15 | * the Free Software Foundation; either version 2 of the License, or |
|---|
| 16 | * (at your option) any later version. |
|---|
| 17 | * |
|---|
| 18 | * This program is distributed in the hope that it will be useful, |
|---|
| 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 21 | * GNU General Public License for more details. |
|---|
| 22 | * |
|---|
| 23 | * You should have received a copy of the GNU General Public License |
|---|
| 24 | * along with this program; if not, write to the Free Software |
|---|
| 25 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|---|
| 26 | * |
|---|
| 27 | * ------------------------------------------------------------------------- |
|---|
| 28 | * |
|---|
| 29 | * This file is not separated into a .h and a .cpp file. The reason is |
|---|
| 30 | * to avoid problems with template initializations of this class. |
|---|
| 31 | * An \c Stack<type> can contain any type and it is not possible to |
|---|
| 32 | * initialize and pre-compile all types that might be put into an |
|---|
| 33 | * \c Stack. |
|---|
| 34 | */ |
|---|
| 35 | |
|---|
| 36 | #ifndef STACK_H |
|---|
| 37 | #define STACK_H |
|---|
| 38 | |
|---|
| 39 | #include <itpp/base/itassert.h> |
|---|
| 40 | |
|---|
| 41 | |
|---|
| 42 | namespace itpp { |
|---|
| 43 | |
|---|
| 44 | /*! |
|---|
| 45 | \brief General stack class |
|---|
| 46 | |
|---|
| 47 | This class is a general stack class for arbitrary types. |
|---|
| 48 | |
|---|
| 49 | For rarely used types you will need to instantiate the class by |
|---|
| 50 | \code |
|---|
| 51 | template class Stack<type>; |
|---|
| 52 | \endcode |
|---|
| 53 | |
|---|
| 54 | The following example shows how to define a Stack of vectors: |
|---|
| 55 | \code |
|---|
| 56 | vec a = randn(10); |
|---|
| 57 | vec b = randn(20); |
|---|
| 58 | Stack<vec> my_stack(10); |
|---|
| 59 | my_stack.push(a); |
|---|
| 60 | my_stack.push(b); |
|---|
| 61 | |
|---|
| 62 | cout << my_stack.pop() << " " << my_stack.pop() << endl ; |
|---|
| 63 | \endcode |
|---|
| 64 | */ |
|---|
| 65 | template<class T> |
|---|
| 66 | class Stack { |
|---|
| 67 | public: |
|---|
| 68 | //! Default constructor |
|---|
| 69 | Stack(); |
|---|
| 70 | //! Create a Stack of size \c n |
|---|
| 71 | Stack(int n); |
|---|
| 72 | //! Create a copy of \c s |
|---|
| 73 | Stack(const Stack<T> &s); |
|---|
| 74 | //! Default destructor |
|---|
| 75 | virtual ~Stack(); |
|---|
| 76 | |
|---|
| 77 | //! Pop the topmost element of the stack |
|---|
| 78 | T pop(); |
|---|
| 79 | //! Peek at the topmost element of the stack, without removing it |
|---|
| 80 | T peek() const; |
|---|
| 81 | //! Push an element at top of stack |
|---|
| 82 | void push(T v); |
|---|
| 83 | //! Empty the stack |
|---|
| 84 | void clear(); |
|---|
| 85 | |
|---|
| 86 | //! Assignment operator |
|---|
| 87 | void operator=(const Stack<T> &s); |
|---|
| 88 | |
|---|
| 89 | //! Returns the maximum number of data elements the stack can store |
|---|
| 90 | int size() const { return ndata; } |
|---|
| 91 | //! Returns the number of data elements currently in the stack |
|---|
| 92 | int no_elements() const { return valptr; } |
|---|
| 93 | //! Resizing a Stack<T>. |
|---|
| 94 | void set_size(int n, bool copy=false); |
|---|
| 95 | |
|---|
| 96 | private: |
|---|
| 97 | int valptr; |
|---|
| 98 | int ndata; |
|---|
| 99 | T *data; |
|---|
| 100 | |
|---|
| 101 | private: |
|---|
| 102 | void alloc(int n); |
|---|
| 103 | void free(); |
|---|
| 104 | }; |
|---|
| 105 | |
|---|
| 106 | // --------------------------- Implementation starts here ---------------------------------- |
|---|
| 107 | |
|---|
| 108 | template<class T> |
|---|
| 109 | Stack<T>::Stack() |
|---|
| 110 | { |
|---|
| 111 | data = 0; |
|---|
| 112 | ndata = 0; |
|---|
| 113 | valptr = 0; |
|---|
| 114 | } |
|---|
| 115 | |
|---|
| 116 | template<class T> |
|---|
| 117 | Stack<T>::Stack(int n) |
|---|
| 118 | { |
|---|
| 119 | alloc(n); |
|---|
| 120 | valptr=0; |
|---|
| 121 | } |
|---|
| 122 | |
|---|
| 123 | template<class T> |
|---|
| 124 | Stack<T>::Stack(const Stack<T> &s) |
|---|
| 125 | { |
|---|
| 126 | data=NULL; |
|---|
| 127 | ndata=0; |
|---|
| 128 | valptr=s.valptr; |
|---|
| 129 | alloc(s.ndata); |
|---|
| 130 | for (int i=0; i<s.ndata; i++) |
|---|
| 131 | data[i] = s.data[i]; |
|---|
| 132 | } |
|---|
| 133 | |
|---|
| 134 | template<class T> |
|---|
| 135 | Stack<T>::~Stack() |
|---|
| 136 | { |
|---|
| 137 | free(); |
|---|
| 138 | } |
|---|
| 139 | |
|---|
| 140 | template <class T> |
|---|
| 141 | T Stack<T>::pop() |
|---|
| 142 | { |
|---|
| 143 | it_error_if(valptr==0,"Stack<T>::pop: Empty stack"); |
|---|
| 144 | valptr--; |
|---|
| 145 | return data[valptr]; |
|---|
| 146 | } |
|---|
| 147 | |
|---|
| 148 | template <class T> |
|---|
| 149 | T Stack<T>::peek() const |
|---|
| 150 | { |
|---|
| 151 | it_error_if(valptr==0,"Stack<T>::peek: Empty stack"); |
|---|
| 152 | return data[valptr-1]; |
|---|
| 153 | } |
|---|
| 154 | |
|---|
| 155 | template <class T> |
|---|
| 156 | void Stack<T>::push(T v) |
|---|
| 157 | { |
|---|
| 158 | it_error_if(valptr>=ndata,"Stack<T>::push: Full stack"); |
|---|
| 159 | data[valptr]=v; |
|---|
| 160 | valptr++; |
|---|
| 161 | } |
|---|
| 162 | |
|---|
| 163 | template <class T> |
|---|
| 164 | void Stack<T>::clear() |
|---|
| 165 | { |
|---|
| 166 | valptr=0; |
|---|
| 167 | } |
|---|
| 168 | |
|---|
| 169 | template<class T> |
|---|
| 170 | void Stack<T>::alloc(int n) |
|---|
| 171 | { |
|---|
| 172 | if (n == 0) { |
|---|
| 173 | data = NULL; |
|---|
| 174 | ndata = 0; |
|---|
| 175 | } |
|---|
| 176 | else { |
|---|
| 177 | data = new T[n]; |
|---|
| 178 | it_assert_debug(data!=0, "Out of memory in Stack::alloc"); |
|---|
| 179 | } |
|---|
| 180 | ndata = n; |
|---|
| 181 | } |
|---|
| 182 | |
|---|
| 183 | template<class T> |
|---|
| 184 | void Stack<T>::free() |
|---|
| 185 | { |
|---|
| 186 | |
|---|
| 187 | delete [] data; |
|---|
| 188 | |
|---|
| 189 | data = 0; |
|---|
| 190 | ndata = 0; |
|---|
| 191 | } |
|---|
| 192 | |
|---|
| 193 | template<class T> |
|---|
| 194 | void Stack<T>::operator=(const Stack<T> &s) |
|---|
| 195 | { |
|---|
| 196 | set_size(s.ndata); |
|---|
| 197 | for (int i=0; i<ndata; i++) |
|---|
| 198 | data[i] = s.data[i]; |
|---|
| 199 | valptr=0; |
|---|
| 200 | } |
|---|
| 201 | |
|---|
| 202 | template<class T> |
|---|
| 203 | void Stack<T>::set_size(int sz, bool copy) |
|---|
| 204 | { |
|---|
| 205 | int i, min; |
|---|
| 206 | T *tmp; |
|---|
| 207 | |
|---|
| 208 | if (ndata == sz) |
|---|
| 209 | return; |
|---|
| 210 | |
|---|
| 211 | if (copy) { |
|---|
| 212 | tmp = data; |
|---|
| 213 | min = ndata < sz ? ndata : sz; |
|---|
| 214 | alloc(sz); |
|---|
| 215 | for (i=0; i<min; i++) |
|---|
| 216 | data[i] = tmp[i]; |
|---|
| 217 | delete [] tmp; |
|---|
| 218 | } else { |
|---|
| 219 | free(); |
|---|
| 220 | alloc(sz); |
|---|
| 221 | } |
|---|
| 222 | ndata = sz; |
|---|
| 223 | } |
|---|
| 224 | |
|---|
| 225 | } // namespace itpp |
|---|
| 226 | |
|---|
| 227 | #endif // #ifndef STACK_H |
|---|