顺序栈-初始化栈顶指针为0

  • 1.头文件及类型定义
  • 2.顺序栈类型定义
  • 3.函数声明
  • 4.基本操作
  • 4.1 初始化顺序栈
  • 4.2 判空
  • 4.3 入栈
  • 4.4 出栈
  • 4.5 读取栈顶元素
  • 4.6 main函数
  • 5.小结


1.头文件及类型定义

#include<stdio.h>
#define MaxSize 10			//定义顺序栈中元素的最大个数
#define ElemType int

2.顺序栈类型定义

typedef struct {		
	ElemType data[MaxSize];		//静态数组存放栈中元素
	int top;					//栈顶指针,一般来说存放数组的下标
}SeqStack;

3.函数声明

/*函数声明*/
void InitStack(SeqStack& S);				//1.初始化顺序栈
bool StackEmpty(SeqStack S);				//2.判空
bool Push(SeqStack& S, ElemType x);			//3.入栈
bool Pop(SeqStack& S, ElemType& x);			//4.出栈
bool GetTop(SeqStack S, ElemType& x);		//5.读取栈顶元素

4.基本操作

4.1 初始化顺序栈

//1.初始化栈
void InitStack(SeqStack& S) {
	S.top = 0;		//初始化栈顶指针为0
}

4.2 判空

//2.判空
bool StackEmpty(SeqStack S) {
	return (S.top == 0);
}

4.3 入栈

//3.入栈操作:新元素入栈(先存再加)
bool Push(SeqStack& S, ElemType x) {
	if (S.top == MaxSize)		//栈满,报错
		return false;
	S.data[S.top] = x;	//新元素先入栈:在栈顶指针所指位置放入x
	S.top++;		//栈顶指针再加1
	/*
		以上两句与此句等价:S.data[S.top++] = x;
		请注意是S.top++,而不是++S.top
	*/
	return true;
}

4.4 出栈

//4.出栈操作:栈顶元素出栈(先减再取)-栈顶元素只是逻辑上被删除了,实际上还残留在内存中
bool Pop(SeqStack& S, ElemType& x) {
	if (S.top == 0)		//栈空,报错
		return false;
	S.top--;				//指针指针先减1
	x = S.data[S.top];		//栈顶元素再出栈:返回栈顶元素的值x
	
	/*
		以上两句与此句等价:x = S.data[--S.top];
		请注意是--S.top,而不是S.top--,注意与上面的入栈操作对比
	*/
	return true;
}

4.5 读取栈顶元素

//5.读取栈顶元素操作
bool GetTop(SeqStack& S, ElemType& x) {
	if (S.top == 0)		//栈空,报错
		return false;
	x = S.data[--S.top];	
	S.top++;	//若SeqStack不是引用类型,则此句不用加
	//以上两句代码建议画图,与初始化指针为-1的顺序栈有所区别
	return true;
}

4.6 main函数

int main() {
	SeqStack S;		//声明一个顺序栈(分配内存空间)

	/*1、初始化栈*/
	InitStack(S);

	/*2、判空*/
	if (StackEmpty(S))
		printf("当前栈空!\n");
	else
		printf("当前栈非空!\n");

	/*3、入栈操作*/
	ElemType e1;
	printf("请输入入栈元素的值:");
	scanf("%d", &e1);
	if (Push(S, e1))
		printf("新元素入栈成功!\n");
	else
		printf("栈已满,新元素入栈失败!\n");

	/*4、读取栈顶元素*/
	ElemType e2 = -1;
	if (GetTop(S, e2))
		printf("读取栈顶元素成功,当前栈顶元素值为:%d\n", e2);
	else
		printf("栈已空,读取栈顶元素失败!\n");

	/*5、出栈操作*/
	ElemType e3 = -1;
	if (Pop(S, e3))
		printf("栈顶元素出栈成功,出栈元素值为:%d\n", e3);
	else
		printf("栈已空,栈顶元素出栈失败!\n");

	/*6、读取栈顶元素*/
	ElemType e4 = -1;
	if (GetTop(S, e4))
		printf("读取栈顶元素成功,当前栈顶元素值为:%d\n", e4);
	else
		printf("栈已空,读取栈顶元素失败!\n");

	return 0;
}

5.小结

  1. 栈顶指针为-1和0的区别
    在遇到相关问题时,一定要注意看清初始化栈顶指针的值
    (1)当初始化为-1时,栈顶指针指向的是当前栈中的实际位置,而当初始化为为0时,栈顶指针指向的是下一次要插入的位置。
    (2)在进行入栈和出栈的操作时,二者核心操作是相反的。
    (3)在获取栈顶元素的操作中,如果初始化栈顶为0,那么需要先对指针减1才能取到栈顶元素的值,这点与初始化栈顶为-1时的操作有所不同。并且,如果函数定义中参数使用了引用传递,那么栈顶指针还需要再加1,保持栈顶指针原来的位置。如果使用值传递,则不需要,因为值传递不会改变原来的栈。
  2. 顺序栈的缺点
    顺序栈是由静态数组实现的,和顺序表一样,它也存在着容量不可改变的缺点,如果刚开始申请的内存空间过大,又存在内存浪费的问题。
    如何解决这个问题呢,一种是仍然使用顺序存储,使用共享栈来提高内存空间的利用率;另一种则是使用链式存储,引入链栈,这两种方式将在接下来的文章中继续讨论。