栈的定义
- 栈是限定仅在表尾进行插入和删除操作的线性表,允许操作的一端称为栈顶,不进行操作的一端称为栈底,不含任何数据元素的栈称为空栈。
- 栈具有“后进后出”的特性,就如同一叠盘子,要从这叠盘子中取出盘子或者放入一个盘子,只有在其顶部操作是最方便的。
1.栈的顺序存储结构——顺序栈
//栈的顺序存储
template <class T>
class SeqStack
{
public:
SeqStack()
{
top = -1; //第一个元素入栈时,其下标为0
}
~SeqStack() {}
void Push(T x) //入栈操作
{
if(top == StackSize - 1)
cout << "上溢";
else
{
//先使top指向下一个位置(top++),再将元素入栈
//通俗的来说,即先选好一个沙发,再请元素x入座。
data[++top] = x;
}
}
T Pop() //出栈操作
{
if(top == -1)
cout << "下溢";
else
{
//先将元素出栈,再使top指向上一个位置(top--)
//通俗的来说,即先请栈顶元素离开,再移走他的沙发。
return data[top--];
}
}
T GetTop()
{
if(top != -1)
return data[top];
}
int Empty()
{
top == -1 ? return 1 : return 0;
}
private:
T data[StackSize]; //存放栈元素的数组
int top; //指向栈顶元素的指针,特别注意的是栈为空时top初始值为-1
};
2.栈的链接存储结构——链栈
//结点
template <class T>
struct Node
{
T data;
Node<T> * next;
};
//栈的链接存储
template <class T>
class LinkStack
{
public:
LinkStack()
{
top = NULL;
}
~LinkStack();
void Push(T x)
{
Node<T> s = new Node<T>;
s->data = x;
s->next = top; //每个结点的next指针域都是指向上一个元素,而不是下一个元素。
top = s;
}
T Pop()
{
if(top == NULL)
cout << "下溢";
//暂存栈顶元素
T x = top->data;
Node<T> p = top;
top = top->next;
delete p;
return x;
}
T GetTop()
{
if(top != NULL)
return top->data;
}
int empty
{
top == NULL ? return 1 : return 0;
}
private:
Node<T> * top;
};
3.顺序栈和链栈的比较
- 实现顺序栈和链栈的基本操作算法所需的时间都是常数时间,所以唯一可以比较的就是空间性能。
- 顺序表必须确定一个固定的长度,所以有存储元素个数的限制和空间浪费的问题。
- 链栈没有栈满的问题,只有内存不够的时才会出现栈满,但是每一个元素都需要一个指针域,从而产生了结构性开销。
- 所以当栈的使用过程中元素个数变化较大时候,用链栈是适宜的;反之,应该采用顺序栈。