栈是一种只允许在一端进行插入或删除操作的线性表.其特点为:先进后出(FILO)/后进先出(LIFO);
栈 VS. 队列
栈和队列都是动态集合, 但在栈中, 可以去掉的是最近插入的那一个,:栈实现了一种后进先出(last-in, first-out)的策略;类似的, 在队列中, 可以去掉的元素总是在集合中存在时间最长的那一个:队列实现了先进先出(first-in, first-out)的策略[下一篇我们着重复习队列].
栈的示意图:
//顺序栈的实现与解析 template <typename Type> class MyStack { template <typename T> friend ostream &operator<<(std::ostream &os, const MyStack<T> &stack); public: MyStack(int stackCapacity = 16); ~MyStack(); bool isEmpty() const; void push(const Type &item); void pop() throw (std::range_error); const Type &top() const throw(std::range_error); private: Type *m_stack; int m_top; int m_capacity; };
template <typename Type> MyStack<Type>::MyStack(int stackCapacity):m_capacity(stackCapacity) { if (m_capacity < 1) throw std::range_error("new size must >= 1"); //申请内存并构造对象 m_stack = new Type[m_capacity]; if (m_stack == NULL) throw std::bad_alloc(); m_top = -1; }
template <typename Type> MyStack<Type>::~MyStack() { //析构对象并释放内存 delete []m_stack; m_stack = NULL; m_top = -1; //将top指针指向无效 m_capacity = 0; }
//全局函数:数组放大/缩小 template <typename Type> static void changeSize1D(Type *&array, int oldSize, int newSize) throw (std::range_error, std::bad_alloc) { if (newSize < 0) throw std::range_error("new size must >= 0"); Type *tmp = new Type[newSize]; if (tmp == NULL) throw std::bad_alloc(); int minSize = std::min(oldSize, newSize); std::copy(array, array+minSize, tmp); delete []array; //将原数组释放掉 array = tmp; //将原指针指向新申请的数组 } template <typename Type> void MyStack<Type>::push(const Type &item) { //数组最大容量为m_capacity, 因此数组的最大下标为m_capacity-1 if (m_top >= m_capacity-1) { changeSize1D(m_stack, m_capacity, m_capacity * 2); //一次扩容2倍 m_capacity *= 2; } //将元素插入栈顶 m_stack[++ m_top] = item; }
//栈是否为空 template <typename Type> inline bool MyStack<Type>::isEmpty() const { return -1 == m_top; }
template <typename Type> inline const Type &MyStack<Type>::top() const throw (std::range_error) { if (isEmpty()) throw std::range_error("stack is empty"); return m_stack[m_top]; //返回栈顶元素 }
template <typename Type> inline void MyStack<Type>::pop() throw (std::range_error) { if (isEmpty()) throw std::range_error("stack is empty"); //注意:如果该栈保存的对象类型的元素, 则需要显示调用其析构函数, //同时还需要将栈顶指针下移 m_stack[m_top --].~Type(); }
//输出栈的所有内容,以便测试 template <typename Type> ostream &operator<<(ostream &os, const MyStack<Type> &stack) { os << stack.m_stack[0]; for (int i = 1; i <= stack.m_top; ++i) os << ' ' << stack.m_stack[i]; return os; }
附-测试代码
int main() { MyStack<int> iStack; iStack.push(10); iStack.push(22); iStack.push(15); cout << iStack << endl; try { cout << "Top = " << iStack.top() << endl; iStack.pop(); cout << "Top = " << iStack.top() << endl; iStack.pop(); cout << "Top = " << iStack.top() << endl; iStack.pop(); cout << "Top = " << iStack.top() << endl; } catch (const std::exception &e) { cout << e.what() << endl; } }