考研数据结构之栈(Stack)

提示 满招损,谦受益


也是以一个思维导图开始栈这场闹剧 考研我们需要知道什么请添加图片描述
请添加图片描述
请添加图片描述
附有高清版

前言

官方一点的话:栈是一种的先进后出 有点像穿糖葫芦的那个果子 先穿后吃(不要告诉我 你从下往上吃哈 )
请添加图片描述

栈本质来说是一种有限制的线性表,所以可以使用线性表的形式来定义栈的结构体,限制了存取只能从栈顶这个位置进行操作怎么限制?较顺序表多设置一个变量 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;	
}

总结(下一篇链栈)

若是文章对你的提升由哪怕一点帮助的话 请答应我 不要吝啬你的点赞评论 你的鼓励对作者是一种莫大的鼓励

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值