一、栈的定义
1.栈是一种特殊的线性表;
2.栈只能在线性表的一端进行操作。即只允许在栈顶(Top)操作,而不允许在栈底(Bottom)操作。
二、栈的特性
由于栈只允许在栈顶(Top)操作,故栈的特性为后进先出(Last In First Out)。如下图所示:
(注:此图引用自狄泰软件学院唐老师ppt)
三、栈的操作
- 创建栈(Stack())
- 销毁栈(~Stack())
- 清空栈(clear())
- 进栈(push())
- 出栈(pop())
- 获取栈顶元素(top())
- 获取栈的大小(size())
四、栈的实现
1.栈的抽象实现:
Stack.h
#ifndef STACK_H
#define STACK_H
namespace Stack {
template <typename T>
class Stack
{
public:
virtual void push(const T& e) = 0;
virtual void pop() = 0;
virtual T top() = 0;
virtual void clear() = 0;
virtual int size() const = 0;
};
}
#endif // STACK_H
2.静态栈的实现:
设计要点:
1.使用原生数组作为栈的存储空间;
2.栈的存储空间在创建栈的时候指定(由模板参数指定),且不能动态的改变。
下面给出静态栈的具体实现:
StaticStack.h
#ifndef STATICSTACK_H
#define STATICSTACK_H
#include "Stack.h"
#include "Exception.h"
namespace Stack {
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("No space in current stack ...");
}
}
void pop()
{
if (m_size > 0) {
m_top --;
m_size --;
} else {
throw("No element in current stack ...");
}
}
T top()
{
if (m_size > 0) {
return m_space[m_top];
} else {
throw("No element in current stack ...");
}
}
void clear()
{
m_top = -1;
m_size = 0;
}
int size() const
{
return m_size;
}
};
}
#endif // STATICSTACK_H
3.链式栈的实现
由于静态栈一次性创建指定大小的空间,如果栈的数据元素为类类型的话,就需要调用N次构造函数,故效率会比较低;另静态栈没法动态的改变栈的大小。
基于以上两点,链式栈便可以解决上述两个问题。
设计要点:
1.用类模板实现,是抽象父类Stack的直接子类;
2.内部实现一个单链表;
3.只在单链表成员对象的头部进行操作。
下面给出链式栈的具体实现:
LinkStack.h
#ifndef LINKSTACK_H
#define LINKSTACK_H
#include "Stack.h"
namespace Stack {
template <typename T>
class LinkStack : public Stack<T>
{
protected:
struct Node {
T value;
struct Node* next;
};
// 为了防止泛指类型T在构造函数中抛出异常,导致栈初始化失败,故重新实现头结构
struct {
char reserved[sizeof(T)];
Node* next;
} m_header;
int m_length;
public:
LinkStack()
{
m_length = 0;
m_header.next = NULL;
}
void push(const T& e)
{
Node* node = new Node();
if (node) {
node->value = e;
if (0 == m_length) {
m_header.next = node;
} else {
node->next = m_header.next;
m_header.next = node;
}
m_length ++;
} else {
throw("No memory to create node ...");
}
}
void pop()
{
if (m_length > 0) {
Node* toPop = m_header.next;
m_header.next = toPop->next;
m_length --;
delete toPop;
} else {
throw( "No element in current stack ...");
}
}
T top()
{
if (m_length > 0) {
return m_header.next->value;
} else {
throw( "No element in current stack ...");
}
}
void clear()
{
while (m_length > 0) {
pop();
}
}
int size() const
{
return m_length;
}
};
}
#endif // LINKSTACK_H