首先我们来学习栈的定义是什么:栈(stack)是限定仅在表尾进行插入和删除操作的线性表。
我们把允许插入和删除的一端称为栈顶(top),另一端称为栈低(bottom),不含任何数据元素的栈称为空栈。栈又称为后进先出(Last In First Out)的线性表,简称LIFO结构。
学习栈要注意的一点是,这个叫做栈的线性表的表尾是指栈顶,而不是栈底。
栈的插入操作叫作进栈、压栈或者入栈。
栈的删除操作叫作出栈或者弹栈。
栈的应用很广泛,比如说实现递归操作,进行四则表达式求值等等。
关于栈的结构定义和各种操作函数,我写了相关代码并用注释的方式进行了详细的讲解,具体请看以下代码:
#include <stdio.h>//我们要实现一个线性结构的栈,只需要引入stdio.h头文件用于打印显示验证就好了
//下面是一堆我不说你也看得懂的宏定义
#define OK 1
#define ERROR 0
#define MAXSIZE 5//为了方便,我定义这个栈的最大容量为5
#define BOOL int
#define TRUE 1
#define FALSE 0
typedef int SElemType;// SElemType类型根据实际情况而定,这里我们假设其为int
typedef int Status;//用作返回函数的执行状态,成功返回OK(1),失败返回(0)
typedef struct//这是栈的结构定义,包含两个成员,一是用了储存栈的数组,二是代表栈顶指针的top
{
SElemType data[MAXSIZE];
int top;
}SqStack;
//一堆函数声明,具体意义和实现方法我会在下面讲
Status Push(SqStack *S,SElemType e);
Status Pop(SqStack *S, SElemType *e);
void InitStack(SqStack *S);
void PrintStack(SqStack *S);
void ClearStack(SqStack *S);
BOOL StackEmpty(SqStack *S);
Status GetTop(SqStack *S,SElemType *e);
int StackLength(SqStack *S);
int main(int argc, char *argv[]) {
SElemType temp;//定义一个临时变量,用于返回元素值
SqStack S1;//声明一个栈S1
SqStack *s1=&S1;//为了方便,我们定义一个指向栈的指针s1
InitStack(s1);//现在我们初始化这个栈
PrintStack(s1);//由于此时栈为空,因此会打印出来一个NULL
//现在我们来进行压栈操作,因为栈的最大容量为5,因此在第六次操作时会返回一个ERROR,同时压栈失败
if(Push(s1,1)==ERROR) printf("ERROR\n");
if(Push(s1,2)==ERROR) printf("ERROR\n");
if(Push(s1,3)==ERROR) printf("ERROR\n");
if(Push(s1,4)==ERROR) printf("ERROR\n");
if(Push(s1,5)==ERROR) printf("ERROR\n");
if(Push(s1,6)==ERROR) printf("ERROR\n");
//打印一下看看,是不是上面所压栈的数字1~5
PrintStack(s1);
//我们现在再来试一下弹栈操作,同时打印出弹出的元素,如果栈为空,那么会弹栈失败并打印出一个ERROR
if(Pop(s1, &temp)) printf("%d\n",temp);
else printf("ERROR\n");
if(Pop(s1, &temp)) printf("%d\n",temp);
else printf("ERROR\n");
if(Pop(s1, &temp)) printf("%d\n",temp);
else printf("ERROR\n");
if(Pop(s1, &temp)) printf("%d\n",temp);
else printf("ERROR\n");
if(Pop(s1, &temp)) printf("%d\n",temp);
else printf("ERROR\n");
if(Pop(s1, &temp)) printf("%d\n",temp);//果然第六次弹栈不会成功的
else printf("ERROR\n");
//我们再来重新压进三个元素,用于验证其它操作
if(Push(s1,10)==ERROR) printf("ERROR\n");
if(Push(s1,11)==ERROR) printf("ERROR\n");
if(Push(s1,12)==ERROR) printf("ERROR\n");
printf("StackLength:%d\n",StackLength(s1));//打印一下栈的长度,没错果然是3
if(GetTop(s1, &temp)) printf("%d\n",temp);//我们来返回一下栈顶元素并打印,与弹栈不同的是不会将栈顶元素弹出
else printf("ERROR\n");
if(StackEmpty(s1)) printf("Empty\n");//测试栈是否为空,因为栈中还有三个元素,此处打印出了Not Empty
else printf("Not Empty\n");
ClearStack(s1);//现在我们清空这个栈
if(StackEmpty(s1)) printf("Empty\n");//果然清空后这个栈又重新变成了空的
else printf("Not Empty\n");
return 0;
}
//若栈S存在,插入新元素e到栈S中并成为栈顶元素
Status Push(SqStack *S, SElemType e)
{
if(S->top == MAXSIZE-1)//如果栈满了,返回ERROR
{
return ERROR;
}
S->top++;//栈顶指针增加一
S->data[S->top]=e;//将新插入元素赋值给栈顶空间
return OK;
}
//弹出栈S中的栈顶元素,并用e返回其值
Status Pop(SqStack *S, SElemType *e)
{
if(S->top == -1)//如果栈为空,则返回ERROR
{
return ERROR;
}
*e=S->data[S->top];//将弹出的栈顶元素赋值给e
S->top--;//栈顶指针减一
return OK;
}
//初始化栈S的空间,创建一个空栈
void InitStack(SqStack *S)
{
int i;
S->top=-1;//栈顶指针指向-1表示栈为空
for(i=0;i<MAXSIZE;i++)//将栈中元素用0进行初始化
{
S->data[i]=0;
}
}
//打印栈S中的所有元素,用于验证各项操作是否成功
void PrintStack(SqStack *S)
{
int i;
if(S->top == -1)//如果栈为空,打印NULL并返回
{
printf("NULL\n");
return;
}
for(i=0;i<=S->top;i++)//栈不为空则打印所有元素
{
printf("%d ",S->data[i]);
}
printf("\n");
}
//将栈S清空
void ClearStack(SqStack *S)
{
int i;
S->top=-1;//将栈顶指针指向-1表示栈为空
for(i=0;i<MAXSIZE;i++)//用0初始化栈空间
{
S->data[i]=0;
}
}
//测试栈S是否为空
BOOL StackEmpty(SqStack *S)
{
if(S->top==-1)//若栈为空,返回TRUE
{
return TRUE;
}
else//若不为空则返回FALSE
{
return FALSE;
}
}
//若栈S存在且非空,用e返回S的栈顶元素
Status GetTop(SqStack *S,SElemType *e)
{
if(S->top==-1)//若栈为空,返回ERROR
{
return ERROR;
}
*e=S->data[S->top];//把栈顶元素的值赋值给e
return OK;
}
//返回栈S的元素个数
int StackLength(SqStack *S)
{
return S->top+1;//因为数组的下标是从0开始的,所以要返回栈顶指针的值加一后的结果。
}
谢谢阅读,图片来源于网络,侵删