关于栈和队列,准备写5篇文章。其中栈的部分包括基于顺序存储结构的栈和链式栈两种,分别是StaticStack和LinkStack。同样队列也有两种,基于顺序存储结构的队列和链式队列,分别是StaticQueue和LinkQueue。最后一篇文章分析栈实现队列和队列实现栈。
本篇先分析怎样实现StaticStack。
栈
栈是一种特殊的线性表,栈仅能在线性表的一端进行操作,特点是先进后出
栈顶(Top):允许操作的一端
栈底(Bottom): 不允许操作的一端
Stack
#ifndef _STACK_H_
#define _STACK_H_
#include "Object.h"
namespace DTLib
{
template <typename T>
class Stack : public Object
{
public:
virtual void push(const T& e) = 0;
virtual void pop() = 0;
virtual T top() const = 0;
virtual void clear() = 0;
virtual int size() const = 0;
};
}
#endif
StaticStack设计要点
(1)使用原生数组作为栈的存储空间;
(2)使用模极参数决定栈的最大容量;
(3)用一个标识不断跟踪栈顶,push和pop的时候要改变这个标识。
#ifndef _STATICSTACK_H_
#define _STATICSTACK_H_
#include "Stack.h"
#include "Exception.h"
namespace DTLib
{
template < typename T, int N>
class StaticStack : public Stack<T>
{
protected:
T m_space[N]; // 原生数组
int m_top; // 栈顶标识(实现栈的重要设计)
int m_size; // 当前栈的大小
public:
StaticStack()
{
m_top = -1;
m_size = 0;
}
int capacity() const // 返回栈的最大存储量
{
return N;
}
void push(const T& e)
{
if (m_size < N)
{
m_space[m_top + 1] = e; // 先赋值,再改变m_top和m_size,为了异常安全
m_top++;
m_size++;
}
else
{
THROW_EXCEPTION(InvalidOperationException, "No space in current stack ...");
}
}
void pop()
{
if (m_size > 0) // 有数据元素才可以出栈
{
m_top--;
m_size--;
}
else
{
THROW_EXCEPTION(InvalidOperationException, "No element in current stack ...");
}
}
T top() const
{
if (m_size > 0) // 有数据元素才可以出栈
{
return m_space[m_top];
}
else
{
THROW_EXCEPTION(InvalidOperationException, "No element in current stack ...");
}
}
void clear() // 赋值标识就行
{
m_top = -1;
m_size = 0;
}
int size() const
{
return m_size;
}
};
}
#endif
测试代码:
#include <iostream>
#include "DualCircleList.h"
#include "StaticStack.h"
using namespace std;
using namespace DTLib;
int main(void)
{
StaticStack<int, 5> stack;
for (int i = 0; i < 5; i++)
{
stack.push(i);
}
while (stack.size() > 0)
{
cout << stack.top() << endl;
stack.pop();
}
return 0;
}
输出:
4
3
2
1
0
先入栈的数字分别是0、1、2、3、4,然而出栈的数字分别是4、3、2、1、0,符合栈的先进后出的特性。
下一篇分析链式栈LinkStack的实现。