栈的定义
栈是一种“先进后出”的数据结构,只能从一个位置进,从一个位置出。
栈的操作
栈具有创建栈,压栈、出栈,获取栈顶元素等操作方式。
栈的分类
栈主要分为两类:静态栈(顺势栈)和动态栈(链式栈)。
静态栈:静态栈主要就是运用数组,类似于一个连续内存的数组,我们只能操作栈顶元素。
动态栈:动态栈的核心是链表,我们也只能操作栈顶元素。
进栈出栈的变换形式
对于栈的元素,进行出栈操作时,最后进栈的元素,不一定只能最后出栈。栈对线性表的插入和删除的位置进行了限制,并没有对元素进出的时间进行限制,也就是说,并不是所有元素都进栈的情况下,事先进去的元素也可以出栈,只要保证栈顶元素出栈就可以了。
例如现在有1、2、3三个元素依次进栈,出栈次序有321,123,132,213,231。这几种出栈次序,而312这种出栈次序是肯定不会有的,因为进栈次序是规定了的。
静态栈
#include <stdio.h>
#include <stdlib.h>
#define P 5 //定义最大栈容量
typedef struct Stack //定义栈
{
int data[P]; //栈中的数据
int top; //栈顶
}stack;
stack Init()//初始化栈
{
stack s;
s.top = -1;
return s;
}
int Push(stack &s,int n) //进栈操作
{
if(s.top == P-1) //进栈的时候必须判断是否栈满
{
printf("stack full\n");
}
s.top++;
s.data[s.top] = n;
if(s.top == P-1) //进栈结束的时候判断是否栈满
{
return 0;
}
return 1;
}
int Come(stack &s) //出栈操作
{
int n;
if(s.top == -1) //出栈的时候必须判断是否栈空
{
printf("stack empty\n");
return 0;
}
n = s.data[s.top];
s.top--;
return n;
}
int main()
{
int n,i=1;
stack s; //定义结构体变量s
s = Init(); //初始化栈
printf("请输入进栈的元素:\n");
while(i)
{
scanf_s("%d",&n);
i = Push(s,n);
}
printf("出栈的结果:");
while(s.top != -1)
{
printf("%d ",Come(s));
}
printf("\n");
system ("pause");
return 0;
}
动态栈
动态栈的做法与链表的头插法很类似,都是先进入的元素后出来。、
动态栈的定义
typedef struct Node //定义一个链栈结点结构体
{
int date; //结点数据
struct Node *next; //结点指针
}*node; //结点名
typedef struct Stack //定义链式栈结构体
{
node top; //栈顶指针
int count; //记录栈结点数量
}stack; //栈名
动态栈的入栈操作
void push(stack *S)
{
int m,i;
int n; //入栈元素
printf("请输入你需要入栈数据的个数: ");
scanf_s("%d",&m);
for(i=0;i<m;i++)
{
printf("你输入的第%d个数据为 :",i+1);
scanf_s("%d",&n); //输入数据
node s = (node)malloc(sizeof(struct Node));//申请一个新结点
s -> date = n; //将数据付给date
s -> next = S->top; //让新建结点的下一个结点等于现在的栈顶结点
S -> top = s; //让新结点成为新的栈顶结点
S -> count ++; //栈中结点数据加一
}
}
动态栈的出栈
void pop(stack *S)
{
node s; //定义一个结点指针变量
if(S->count == 0) //判断栈是否为空
{
printf("栈空\n");
exit(0);
}
printf("出栈结果为: ");
while(S->count != 0)
{
s = S->top; //让新定义的结点指针指向当前栈顶
printf("%d ",s->date); //输出结点数据
S->top=s->next; //让栈顶指针指向栈顶结点的下一个结点
free(s); //释放掉结点s
S->count--; //结点个数减一
}
printf("\n\n");
}
栈取栈顶元素
void Gettop(stack *S)
{
if(S->count == 0) //判断栈是否为空
{
printf("栈空\n");
exit(0);
}
printf("栈顶元素为: ");
printf("%d ",S->top->date); //输出结点数据
printf("\n\n");
}
主程序
int main()
{
int i; //用于选择的变量
stack S; //创建栈变量
S.count = 0; //初始化
while(1)
{
printf("请选择下列操作\n");
printf("1:进栈操作\n");
printf("2:出栈操作\n");
printf("3:取栈顶元素\n");
printf("4:退出\n");
scanf_s("%d",&i);
switch(i)
{
case 1:push(&S); break; //进栈操作
case 2:pop(&S); break; //出栈操作
case 3:Gettop(&S);break; //取栈顶元素
case 4:exit(0); //退出程序
default:
printf("输入错误,请重新输入!!!\n");
break;
}
}
printf("\n");
system ("pause");
return 0;
}
输出结果
链式栈与静态栈最大的区别就是,链式栈不用确定栈的最大容量,不用担心容量不够的情况。
栈的作用
我们学习栈到底有什么作用呢?他和数组类似,那我们学习了数组又为何要学习栈。因为栈的引入简化了程序设计的问题,划分了不同关注层次,使得思考范围缩小,更加聚焦于我们要解决的问题核心。反之,像数组等,要分散精力去考虑数组的下标增减等细节问题,反而掩盖了问题的本质。