1.头文件及类型定义
#include<stdio.h>
#define MaxSize 10
#define ElemType int
2.顺序栈类型定义
typedef struct {
ElemType data[MaxSize];
int top;
}SeqStack;
3.函数声明
void InitStack(SeqStack& S);
bool StackEmpty(SeqStack S);
bool Push(SeqStack& S, ElemType x);
bool Pop(SeqStack& S, ElemType& x);
bool GetTop(SeqStack S, ElemType& x);
4.基本操作
4.1 初始化顺序栈
void InitStack(SeqStack& S) {
S.top = 0;
}
4.2 判空
bool StackEmpty(SeqStack S) {
return (S.top == 0);
}
4.3 入栈
bool Push(SeqStack& S, ElemType x) {
if (S.top == MaxSize)
return false;
S.data[S.top] = x;
S.top++;
return true;
}
4.4 出栈
bool Pop(SeqStack& S, ElemType& x) {
if (S.top == 0)
return false;
S.top--;
x = S.data[S.top];
return true;
}
4.5 读取栈顶元素
bool GetTop(SeqStack& S, ElemType& x) {
if (S.top == 0)
return false;
x = S.data[--S.top];
S.top++;
return true;
}
4.6 main函数
int main() {
SeqStack S;
InitStack(S);
if (StackEmpty(S))
printf("当前栈空!\n");
else
printf("当前栈非空!\n");
ElemType e1;
printf("请输入入栈元素的值:");
scanf("%d", &e1);
if (Push(S, e1))
printf("新元素入栈成功!\n");
else
printf("栈已满,新元素入栈失败!\n");
ElemType e2 = -1;
if (GetTop(S, e2))
printf("读取栈顶元素成功,当前栈顶元素值为:%d\n", e2);
else
printf("栈已空,读取栈顶元素失败!\n");
ElemType e3 = -1;
if (Pop(S, e3))
printf("栈顶元素出栈成功,出栈元素值为:%d\n", e3);
else
printf("栈已空,栈顶元素出栈失败!\n");
ElemType e4 = -1;
if (GetTop(S, e4))
printf("读取栈顶元素成功,当前栈顶元素值为:%d\n", e4);
else
printf("栈已空,读取栈顶元素失败!\n");
return 0;
}
5.小结
- 栈顶指针为-1和0的区别
在遇到相关问题时,一定要注意看清初始化栈顶指针的值。
(1)当初始化为-1时,栈顶指针指向的是当前栈中的实际位置,而当初始化为为0时,栈顶指针指向的是下一次要插入的位置。
(2)在进行入栈和出栈的操作时,二者核心操作是相反的。
(3)在获取栈顶元素的操作中,如果初始化栈顶为0,那么需要先对指针减1才能取到栈顶元素的值,这点与初始化栈顶为-1时的操作有所不同。并且,如果函数定义中参数使用了引用传递,那么栈顶指针还需要再加1,保持栈顶指针原来的位置。如果使用值传递,则不需要,因为值传递不会改变原来的栈。 - 顺序栈的缺点
顺序栈是由静态数组实现的,和顺序表一样,它也存在着容量不可改变的缺点,如果刚开始申请的内存空间过大,又存在内存浪费的问题。
如何解决这个问题呢,一种是仍然使用顺序存储,使用共享栈来提高内存空间的利用率;另一种则是使用链式存储,引入链栈,这两种方式将在接下来的文章中继续讨论。