提示 满招损,谦受益
也是以一个思维导图开始栈这场闹剧 考研我们需要知道什么
附有高清版
前言
官方一点的话:栈是一种的先进后出 有点像穿糖葫芦的那个果子 先穿后吃(不要告诉我 你从下往上吃哈 )
栈本质来说是一种有限制的线性表,所以可以使用线性表的形式来定义栈的结构体,限制了存取只能从栈顶这个位置进行操作怎么限制?较顺序表多设置一个变量 top,top是栈顶标志,根据约定只能由top找栈顶元素
关于栈的结构体定义可见这一篇博文关于三种栈三种结构体解析
还有就是需要对栈中的一些注意事项进行一波讲解
1、入栈需要判断是否栈满
2、出栈需要判断栈是否为空
3、初始化的时候 top有定义在 base 下面的相当于是-1 也有定义和base 一起的相当于是零,不同的定义形式影响着是不是先加再赋值 还是先赋值再加 所以也就是具体问题具体分析,下面代码使用的是top初始化为0。
定义的
结构体
typedef struct
{
SElemType *base;
SElemType *top;
int capacity; //可用最大容量
}SqStack;
提示:以下是本篇文章正文内容,下面案例可供参考
一、重点代码块分析
1、初始化
重点要理解代码每一个人写出来的都可能是不一样的,这里我申请的空间是MAX+1因为我刚开始的时候给top 赋值是base一样的 所以导致最后栈满的时候 top会越界,所以我们多申请一个空间,其实不多申请好像也没有什么影响 因为我们不会取到s.top (取栈顶的时候是*–s.top)
bool InitStack(Stack &S){
//当然这里也可以将MAX设置成变量,这里就不写了 要是想知道可以参考动态顺序表那一篇
S.base=(ElemType*)malloc((MAX+1)*sizeof(ElemType));
//使用了malloc就需要判断是否空间申请成功
if(S.base==NULL){
//printf("空间申请失败\n");
exit(1);
}
S.top=S.base;
S.capacity=MAX;
}
2、进栈
这里使用的是线性表中的动态顺序表,动态会写,其实静态就更加简单了,要注意的是空间重新申请别忘了capacity重新赋值,还有就是我们是先填入数据再++,若是top初始化为-1 则是先++再填充数据。
bool Push(Stack &S,ElemType &x){
int choice;
if(S.top-S.base==S.capacity){
//此时栈已经满
printf("栈已满请问是否知道暗号?\n");
cin>>choice;
switch(choice){
case 1:{
return false;
}
case 2:{
if(0==S.capacity){
cout<<"没有空间还想入栈?"<<endl;
break;
}
S.base=(ElemType*)realloc(S.base,S.capacity*2+1);
S.capacity=S.capacity*2;
break;
}
default:break;
}
}
*(S.top++)=x;//这里是先用再加
cout<<"进行进栈操作之后";PrintStack(S);
return true;
}
3、出栈
同样的因为top指向的是栈顶元素的上一个位置 所以需要先减减再取值 但是出栈的时候别忘了判空
//pop为弹出操作 ,弹出之前需要判断是否已经为空 弹出不需要释放空间
bool Pop(Stack &S,ElemType &x){
if(S.base==S.top) return false;
else{
x=*(--S.top); //注意这里是先减再用。
}
cout<<"进行出栈之后的操作是";PrintStack(S);
return true;
}
获取栈顶元素
注意栈顶为空 跟栈顶为零可不是一回事 这里不是减减 ,因为只是获取 而若是减减top的话下一次取就是栈顶的下一个元素 注意与弹出的区别
bool GetTop(Stack S,ElemType &x){
if(S.base==S.top) return false;
else{
x=*(S.top-1); //注意这里不是减减,不能改变topd的位置指向
}
return true;
}
销毁栈
bool DestoryStack(Stack &S){
S.capacity=0;
free(S.base);
S.base=NULL;
S.top=NULL;
return true;
}
可执行代码汇总
//InitStack(&S):初始化一个空栈
//StackEmpty(S)判断一个栈是否为空,若是为空则返回turn 否则返回false
//Push(&S,&x):进栈若是栈未满,则将x加入使之成为新的栈顶
//Pop(&S,&x):出栈,若是栈非空,则弹出栈顶元素,并用X返回、
//GetTop(S,&x):读栈顶元素,若是栈顶元素非空,则用x返回栈顶元素
//DestoryStack(&S):销毁栈,并释放栈S占用的存储空间(&表引用调用)
#include<bits/stdc++.h>
#define ElemType int
#define OK 1
#define ERROR 0
#define MAX 3
using namespace std;
typedef struct Stack{
ElemType* top;
ElemType* base;
int capacity;//定义一个最大容量
}Stack;
//在我写打印的时候突然想到若是栈满 再来打印的话 最后的指针就会越界,此时就不能* S.top
//所以这里你就应该知道为什么有的书上设置top开始的值为-1
void PrintStack(Stack &S){
cout<<"此时栈中的元素是(右边为栈顶)";
for(ElemType* i=S.base;i!=S.top;i++){
cout<<*i<<" ";
}
cout<<endl;
}
bool InitStack(Stack &S){
//当然这里也可以将MAX设置成变量,这里就不写了 要是想知道可以参考动态顺序表那一篇
S.base=(ElemType*)malloc((MAX+1)*sizeof(ElemType));
//使用了malloc就需要判断是否空间申请成功
if(S.base==NULL){
//printf("空间申请失败\n");
exit(1);
}
S.top=S.base;
S.capacity=MAX;
}
bool StackEmpty(Stack S){
if(S.base==S.top) return true;
else return false;
}
//压入栈 ,你要结合你设置的top来确定是先加还是先填数 ,不同的可能是不同的判断方式
//还有进栈就是要判断此时是否栈满
bool Push(Stack &S,ElemType &x){
int choice;
if(S.top-S.base==S.capacity){
//此时栈已经满
printf("栈已满请问是否知道暗号?\n");
cin>>choice;
switch(choice){
case 1:{
return false;
}
case 2:{
if(0==S.capacity){
cout<<"没有空间还想入栈?"<<endl;
break;
}
S.base=(ElemType*)realloc(S.base,S.capacity*2+1);
S.capacity=S.capacity*2;
break;
}
default:break;
}
}
*(S.top++)=x;//这里是先用再加
cout<<"进行进栈操作之后";PrintStack(S);
return true;
}
//pop为弹出操作 ,弹出之前需要判断是否已经为空 弹出不需要释放空间
bool Pop(Stack &S,ElemType &x){
if(S.base==S.top) return false;
else{
x=*(--S.top); //注意这里是先减再用
}
cout<<"进行出栈之后的操作是";PrintStack(S);
return true;
}
bool GetTop(Stack S,ElemType &x){
if(S.base==S.top) return false;
else{
x=*(S.top-1); //注意这里不是减减,不能改变topd的位置指向
}
return true;
}
bool DestoryStack(Stack &S){
S.capacity=0;
free(S.base);
S.base=NULL;
S.top=NULL;
return true;
}
void menu(){
cout<<"请选择你要进行的操作"<<endl;
cout<<"1、判断栈是否为空 2、进栈 3、出栈 "<<endl;
cout<<"4、获得栈顶的值 5、销毁栈 6、展示栈中的内容 7、退出"<<endl;
}
int main(){
Stack S;ElemType x;
InitStack(S);
int choice;
while(1){
menu();
cin>>choice;
if(7==choice) break;
switch(choice){
case 1:{
StackEmpty(S);
break;
}
case 2:{
cout<<"请输入你要入栈的值"<<endl;
cin>>x;
Push(S,x);
break;
}
case 3:{
Pop(S,x);
break;
}
case 4:{
GetTop(S,x);
cout<<"此时栈顶元素是"<<x;
break;
}
case 5:{
DestoryStack(S);
break;
}
case 6:{
PrintStack(S);
break;
}
default:break;
}
}
return 0;
}
总结(下一篇链栈)
若是文章对你的提升由哪怕一点帮助的话 请答应我 不要吝啬你的点赞评论 你的鼓励对作者是一种莫大的鼓励