栈(Stack)作为一种限定性线性表,是将线性表的插入和删除操作限制为仅在表的一端进行,通常将表中允许进行插入、删除操作的一端成为栈顶(Top),因此栈顶的当前位置是动态变化的,它由一个成为栈顶指针的位置指示器来指示。同时,表的另一端被称为栈底(Bottom)。当栈中没有元素时成为空栈。栈的插入操作被形象地成为进栈或入栈,删除操作称为出栈或退栈。
栈被称为时后进先出(Last In First Out,LIFO)的线性表,简称LIFO表。生活中也有很多last in first out的例子,例如,手枪子弹夹中的子弹,子弹装入与子弹出膛均在弹夹的一端进行,现装入的子弹后发出,而后装入的子弹先发出。又如,铁路调度站。
顺序栈是用顺序存储结构实现的栈,即利用各一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时由于栈操作的特殊性,还必须附设一个位置指针(栈顶指针)来动态地知识栈顶元素在顺序栈中的位置。通常以 t o p = − 1 top=-1 top=−1表示空栈。
实现顺序栈各种基本运算
以菜单的形式作为用户与程序的接口,用户输入菜单号来实行相应的操作。
设计几个函数来实现初始化、插入、删除和查找的功能,然后再主函数中调用函数来实现操作。
导入一些库,并定义栈的大小以及表中元素的类型。
#include
#include
#include
#define Stack_Size 50//设栈中元素个数为50
定义栈中元素的数据类型以及顺序栈的存储结构。
typedef int StackElementType;
typedef struct
{
StackElementType elem[Stack_Size];//设置一个一维数组来存放栈中元素
int top;//栈顶指针,是假指针,准确来说应该是指示器
}SeqStack;
初始化顺序栈。
//初始化顺序栈
void Init_Stack(SeqStack *S)
{
S->top=-1;//通常以top=-1表示空栈
}
顺序栈进栈
//顺序栈进栈
int Push(SeqStack *S,StackElementType x)
{
if(S->top==Stack_Size-1)//栈满了,因为是数组存储,所以是-1
return 0;
S->top++;//栈顶指针+1
S->elem[S->top]=x;//进栈
return 1;
}
顺序栈出栈
//顺序栈出栈
int Pop(SeqStack *S)
{
if(S->top==-1)
return 0;
S->top--;
return 1;
}
读取栈顶元素
//读取栈顶元素
StackElementType GetTop(SeqStack *S)
{
StackElementType x;
if(S->top==-1)
return 0;
else
{
x=S->elem[S->top];
printf("%d",x);
return x;
}
}
顺序栈的显示
//顺序栈的显示
void Display_SeqStack(SeqStack *S)
{
int i;
if(S->top==-1)
{
printf("顺序栈为空");
}
else
{
for(i=0;i<=S->top;i++)
{
printf("%d ",S->elem[i]);
}
}
}
主函数部分,用一种“菜单”的形式使线性表的操作更加地清晰地展示出来。
int main()
{
SeqStack s;
int i=1;
StackElementType x;
Init_Stack(&s);
for(x=1;x<5;x++)
{
Push(&s,x);
}
//Display_SeqStack(&s);
while(i)//保证一直进行,条件可以自己改,有很多种方式,比较自由
{
printf("当前的顺序栈如下(栈底->栈顶):\n");
Display_SeqStack(&s);
printf("\n------------------------------------\n");
printf(" Main Menu \n");
printf(" 1 进栈 \n");
printf(" 2 出栈 \n");
printf(" 3 读取栈顶元素 \n");
printf(" 4 清屏 \n");
printf(" 0 结束程序 \n");
printf("------------------------------------\n");
printf("请输入你选择的菜单号<1, 2, 3, 4, 0>:\n");
scanf("%d",&i);
switch(i)
{
case 1:
printf("请输入进栈元素:");
scanf("%d",&x);
Push(&s,x);
//Display_SeqStack(&s);
printf("\n\n");
break;
case 2:
Pop(&s);
//Display_SeqStack(&s);
printf("\n\n");
break;
case 3:
printf("栈顶元素为:");
GetTop(&s);
printf("\n\n");
break;
case 4:
system("cls");
break;
case 0:
exit(0);
break;
default:
printf("输入有误~\n");
break;
}
}
}
实验结果很不错,所有操作都能正常执行,并且自己加入了“清屏”选项,使得界面更加的整洁。
顺序栈比较简单,多多重复,百炼成钢!
最后附上完整的代码
#include
#include
#include
#define Stack_Size 50//设栈中元素个数为50
typedef int StackElementType;
typedef struct
{
StackElementType elem[Stack_Size];//设置一个一维数组来存放栈中元素
int top;//栈顶指针,是假指针,准确来说应该是指示器
}SeqStack;
//初始化顺序栈
void Init_Stack(SeqStack *S)
{
S->top=-1;//通常以top=-1表示空栈
}
//顺序栈进栈
int Push(SeqStack *S,StackElementType x)
{
if(S->top==Stack_Size-1)//栈满了,因为是数组存储,所以是-1
return 0;
S->top++;//栈顶指针+1
S->elem[S->top]=x;//进栈
return 1;
}
//顺序栈出栈
int Pop(SeqStack *S)
{
if(S->top==-1)
return 0;
S->top--;
return 1;
}
//读取栈顶元素
StackElementType GetTop(SeqStack *S)
{
StackElementType x;
if(S->top==-1)
return 0;
else
{
x=S->elem[S->top];
printf("%d",x);
return x;
}
}
//顺序栈的显示
void Display_SeqStack(SeqStack *S)
{
int i;
if(S->top==-1)
{
printf("顺序栈为空");
}
else
{
for(i=0;i<=S->top;i++)
{
printf("%d ",S->elem[i]);
}
}
}
int main()
{
SeqStack s;
int i=1;
StackElementType x;
Init_Stack(&s);
for(x=1;x<5;x++)
{
Push(&s,x);
}
//Display_SeqStack(&s);
while(i)//保证一直进行
{
printf("当前的顺序栈如下(栈底->栈顶):\n");
Display_SeqStack(&s);
printf("\n------------------------------------\n");
printf(" Main Menu \n");
printf(" 1 进栈 \n");
printf(" 2 出栈 \n");
printf(" 3 读取栈顶元素 \n");
printf(" 4 清屏 \n");
printf(" 0 结束程序 \n");
printf("------------------------------------\n");
printf("请输入你选择的菜单号<1, 2, 3, 4, 0>:\n");
scanf("%d",&i);
switch(i)
{
case 1:
printf("请输入进栈元素:");
scanf("%d",&x);
Push(&s,x);
//Display_SeqStack(&s);
printf("\n\n");
break;
case 2:
Pop(&s);
//Display_SeqStack(&s);
printf("\n\n");
break;
case 3:
printf("栈顶元素为:");
GetTop(&s);
printf("\n\n");
break;
case 4:
system("cls");
break;
case 0:
exit(0);
break;
default:
printf("输入有误~\n");
break;
}
}
}