栈
1:栈的相关概念
栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素(至于将术语定义为stack:n(整齐的)一堆)可以体现栈的特性,比如添加新的数据肯定只能放在一堆的顶部(可以反应栈的逻辑关系)
重要的术语:栈顶、栈底、空栈
对于栈的存储形式可以想象成立体的存储方式:
(空栈)在一个立体的空间中存放数据 a5为栈顶,a1为栈底(进栈顺序:a1->a2->a3->a4->a5)
规则:栈顶是允许插入和删除数据的,栈底是不允许插入和删除的
也就是说压入(插入)是增加数据,弹出(删除)是删除数据 ,这些操作只能从栈顶即最低地址入手操作(地址从上往下增加)
栈顶特点:栈作为一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)如上图(出栈顺序:a5->a4->a3->a2->a1)
在学习栈之前首先应了解栈的基本概念以及一些规矩和特点可以加深对栈的理解
和普通线性表的联系:
数据都具有相邻一前一后的特点,但是对插入和删除有较大区别
2:栈顺序存储各项功能的实现
简述:声明、初始化、进栈、出栈、插入数据集(压入)、删除数据(出栈)、判断栈为空/满
2.1>声明
这里没有使用malloc,而是定义了SqStack去定义。所以在程序运行结束后会自动回收空间(这里就省略销毁代码)
#include<stdio.h>
#define MaxSize 5//栈中最大存储数量
typedef struct
{
int data[MaxSize];//定义一个静态数组存放栈的数据
int top;//栈顶指针
}SqStack;//tepedef重命名
void main()
{
SqStack S;//声明一个顺序栈(与此同时计算机已分配空间)
}
在声明中使用tepedef对结构体重命名SqStack,Sq为sequence(n:顺序)的缩写。所以是一个顺序栈同时分配地址空间
2.2>初始化
分析:在声明和分配地址空间之后栈目前是空栈,栈顶指针是指向栈顶元素(空栈中栈顶也是栈底)。此时将栈顶指针指向一个具有代表的地址,以此说明为空栈
void InitStack(SqStack&S)
{
S.top = -1;//初始化栈顶指针
}
.和->使用的条件:“点”是用调用结构中的成员变量;如果是指向一个结构的指针,可以用->shu替换(这里top是成员变量)
2.3>判空
void StackEmpty(SqStack S)
{
if (S.top == -1)
printf("当前栈为空!\n");
else
printf("当前栈非空!\n");
}
2.4>添加数据
输入数据两种情况:定义n为输入数据的数量
1:若n<maxsize,则说明栈没有填满
2:若n>maxsize,则说明栈空间不足当栈满时应停止输入
void CreatStack(SqStack&S,int n)//输入数据
{
printf("向栈中添加%d个数据:\n",n);
int value;//保存每个位置的数据
if (n < MaxSize)
{
while (S.top != n-1)
{
S.top = S.top + 1;//此时栈顶指针指向了栈底
printf("data[%d]=", S.top);
scanf("%d", &value);
S.data[S.top] = value;//将数据传到第一个底部
}
printf("栈添加%d个数据完成!\n", S.top+1);
}
else {
while (S.top != MaxSize-1)
{
S.top = S.top + 1;//此时栈顶指针指向了栈底
printf("data[%d]=", S.top);
scanf("%d", &value);
S.data[S.top] = value;//将数据传到第一个底部
if (S.top == MaxSize - 1)//栈已满
printf("栈已满无法入栈!\n");
}
printf("栈添加%d个数据完成!剩余%d个数据无法入栈\n", S.top+1,n-(S.top+1));
}
}
在初始中将top为-1在栈底的下方,在输入数据时top应一直指向栈顶。所以应先将top移动到栈底才开始输入数据
如果输入过程中栈已满,则应停止输入数据。
2.5>输出栈中元素
栈满足先进后出的原则存储数据,所以对栈表的出栈顺序是从栈顶开始出栈
输出也是对应两种情况:一种是栈还有剩余空间一种是满栈输出
void ShowStack(SqStack S)//打印
{
printf("打印栈数据:\n");
while(S.top!=-1)
{
printf("data[%d]=%d\n",S.top,S.data[S.top]);
S.top--;//从栈顶向下移动
}
}
2.6>插入(压入)
插入不同顺序表和链表,栈的插入删除只可以在栈顶操作
push(v:推动(人或物);移动(身体部位);推进(道路);挤开;推动;)
插入应先进行判断栈是否有空余的空间,如果有要将top节点先上移到新的栈顶节点,然后进行数据的赋值
void PushStack(SqStack &S, int e)//插入
{
if (S.top == MaxSize - 1)
printf("抱歉栈已满无法插入!\n");
S.top = S.top + 1;//将top的位置向上移动到新的栈顶位置
S.data[S.top] = e;
}
2.7>删除(弹出)
先将删除的栈顶数据进行保存,再将top进行下移到新的栈顶
这里的删除只是逻辑上的删除,栈顶(旧)数据还是真实存在于计算机内地的
void PopStack(SqStack &S)//删除栈顶元素
{
int e;
e = S.data[S.top];//将弹出数据保存
S.top--;//top向下移动到达新的栈顶
printf("删除栈顶数据%d\n",e);
}
3:整体代码
#include<stdio.h>
#define MaxSize 6//栈中最大存储数量
typedef struct
{
int data[MaxSize];//定义一个静态数组存放栈的数据
int top;//栈顶指针
}SqStack;//tepedef重命名
void InitStack(SqStack&S)//初始化
{
S.top = -1;//初始化栈顶指针
}
void StackEmpty(SqStack S)//判断空
{
if (S.top == -1)
printf("当前栈为空!\n");
else
printf("当前栈非空!\n");
}
void CreatStack(SqStack&S,int n)//输入数据
{
printf("向栈中添加%d个数据:\n",n);
int value;//保存每个位置的数据
if (n < MaxSize)
{
while (S.top != n-1)
{
S.top = S.top + 1;//此时栈顶指针指向了栈底
printf("data[%d]=", S.top);
scanf("%d", &value);
S.data[S.top] = value;//将数据传到第一个底部
}
printf("栈添加%d个数据完成!\n", S.top+1);
}
else {
while (S.top != MaxSize-1)
{
S.top = S.top + 1;//此时栈顶指针指向了栈底
printf("data[%d]=", S.top);
scanf("%d", &value);
S.data[S.top] = value;//将数据传到第一个底部
if (S.top == MaxSize - 1)//栈已满
printf("栈已满无法入栈!\n");
}
printf("栈添加%d个数据完成!剩余%d个数据无法入栈\n", S.top+1,n-(S.top+1));
}
}
void PushStack(SqStack &S, int e)//插入
{
if (S.top == MaxSize - 1)
printf("抱歉栈已满无法插入!\n");
S.top = S.top + 1;//将top的位置向上移动到新的栈顶位置
S.data[S.top] = e;
}
void PopStack(SqStack &S)//删除栈顶元素
{
int e;
e = S.data[S.top];//将弹出数据保存
S.top--;//top向下移动到达新的栈顶
printf("删除栈顶数据%d\n",e);
}
void ShowStack(SqStack S)//打印
{
printf("打印栈数据:\n");
while(S.top!=-1)
{
printf("data[%d]=%d\n",S.top,S.data[S.top]);
S.top--;//从栈顶向下移动
}
}
void main()
{
SqStack S;//声明一个顺序栈(与此同时计算机已分配空间)
InitStack(S);//初始化栈
StackEmpty(S);//判空
CreatStack(S,5);//向栈中添加数据
PushStack(S, 99);//插入元素到栈顶
ShowStack(S);//打印栈中数据
PopStack(S);//删除栈顶数据
}