栈的顺序表和链表实现,以及一些涉及到栈思想的题目

一、std里面栈的基本操作

#include <stdio.h>
#include <stack>
//使用命名空间std 
using namespace std;
stack<char> s; 
int main()
{
    //判断栈是否为空
	if(s.empty()){
		printf("空\n");
	}
	else{
		printf("非空\n");
	}
	char asd='a';
    //入栈
	s.push(asd);
	s.push('b');
	s.push('c');
	s.push('d');
	s.push('e');
    //获取栈顶元素
	printf("%c\n",s.top());
    //出栈
	s.pop();
	printf("%c\n",s.top());
	if(s.empty()){
		printf("空\n");
	}
	else{
		printf("非空\n");
	}
    //获取栈内元素个数
	printf("%d\n",s.size());
	return 0;
}

二、用顺序表实现栈的基本操作

#include <stdio.h>
#include <stdlib.h>
#define MaxSize 100
typedef char ElemType;
typedef struct{
	ElemType data[100];
	int top;
}SqStack;
//初始化栈
void InitStack(SqStack *&s)
{
	s=(SqStack *)malloc(sizeof(SqStack));
	s->top=-1;
} 
//判断栈是否为空
bool StackEmpty(SqStack *s)
{
	return s->top==-1;	
} 
//将元素e入栈 
bool Push(SqStack *&s, ElemType e)
{
	if(s->top==MaxSize-1){
		return false;
	}
	s->top++; 
	s->data[s->top]=e;
	return true;
}
//将栈顶元素赋值给变量e,然后出栈 
bool Pop(SqStack *&s, ElemType &e)
{
	//如果栈为空,无法出栈 
	if(s->top==-1){
		return false; 
	} 
	e=s->data[s->top]; 
	s->top--;
	return true;
} 
//释放栈
void DestroyStack(SqStack *&s)
{
	free(s);
} 
int main()
{
	//新建一个栈,命名为asd 
	SqStack *asd;
	ElemType e;
	//初始化栈 
	InitStack(asd);
	//判断栈是否为空 
	if(StackEmpty(asd)){
		printf("栈为空\n");
	}
	else{
		printf("栈不为空\n");
	}
	//依次入栈'a'、'b'、'c'、'd'、'e' 
	Push(asd, 'a');
	Push(asd, 'b');
	Push(asd, 'c');
	Push(asd, 'd');
	Push(asd, 'e');
	//判断栈是否为空 
	if(StackEmpty(asd)){
		printf("栈为空\n");
	}
	else{
		printf("栈不为空\n");
	}
	//输出出栈序列 
	Pop(asd, e);
	printf("%c ", e);
	Pop(asd, e);
	printf("%c ", e);
	Pop(asd, e);
	printf("%c ", e);
	Pop(asd, e);
	printf("%c ", e);
	Pop(asd, e);
	printf("%c\n", e);
	//判断栈是否为空 
	if(StackEmpty(asd)){
		printf("栈为空\n");
	}
	else{
		printf("栈不为空\n");
	}
	//释放栈 
	DestroyStack(asd);
	return 0;
}

三、用链表实现栈的基本操作

#include <stdio.h>
#include <stdlib.h>
//默认头结点后面第一个位置为栈顶 
typedef char ElemType;
typedef struct linknode
{
	ElemType data;	//数据域 
	struct linknode *next;	//指针域 
}LinkStNode;	//链表实现的栈结点类型
//初始化栈,由于会改变栈s,所以需要引用& 
void InitStack(LinkStNode *&s)
{
	//开辟一片空间 
	s=(LinkStNode *)malloc(sizeof(LinkStNode));
	s->next=NULL;	//栈顶为空 
} 
//判断栈是否为空,由于不改变栈s,所以不需要加引用&  
bool StackEmpty(LinkStNode *s) 
{
	if(s->next==NULL){
		return true;
	}
	else{
		return false;
	}
	//return (s->next==NULL);
}
//将元素e入栈,要在栈顶入栈,栈顶为头结点后的第一个节点,所以用头插法 
void Push(LinkStNode *&s, ElemType e)
{
	//新建一个节点 
	LinkStNode *p; 
	//为该节点分配空间
	p=(LinkStNode *)malloc(sizeof(LinkStNode));
	//为data域赋值 
	p->data=e;
	//将p和后面的节点(旧的栈顶节点)连一条箭头 
	p->next=s->next; 
	//将头结点和节点p(新的栈顶节点)连一条箭头 
	s->next=p;
} 
//把栈顶元素赋值给变量e,并出栈
//由于调用该函数想要改变e的值,所以e前面需要加引用  
//栈顶为头结点s后的第一个数据结点 
bool Pop(LinkStNode *&s, ElemType &e)
{
	//首先需要判断栈是否为空
	if(s->next==NULL){
		return false;
	}
	//p指针用来保存旧栈顶,否则待会free时就找不到旧栈顶了 
	LinkStNode *p;
	p=s->next;
	e=p->data;
	//将头结点连到栈顶后面那个结点 
	s->next=p->next; //删除首节点 
	free(p);	//释放被删除结点的存储空间 
	return true; 
} 
//销毁栈,依次释放每一个结点的空间 
void DestroyStack(LinkStNode *&s)
{
	//定义栈结点变量,不需要申请空间 
	LinkStNode *p, *q;
	p=s;	//最开始给p赋值为头结点 
	q=s->next;	//给q赋值为第一个数据结点 
	while(q!=NULL){	//只要q不为空,则p就没用了 
		free(p);	//释放p的内存空间 
		p=q;		//p往后挪一位,挪到q的位置 
		q=q->next;	//q也往后挪一位 
	} 
	//最后跳出while循环的时候,q已经为空了,只剩下q一个非空结点 
	free(p);		
} 
int main()
{
	ElemType e;
	//定义一个栈asd 
	LinkStNode *asd;
	//初始化栈asd 
	InitStack(asd); 
	//判断栈是否为空
	if(StackEmpty(asd)==true){
		printf("栈为空\n");
	}
	else{
		printf("栈非空\n");
	}
	//依次入栈元素'a'、'b'、'c'、'd'、'e'
	Push(asd, 'a');
	Push(asd, 'b');
	Push(asd, 'c');
	Push(asd, 'd');
	Push(asd, 'e');
	//判断栈是否为空
	if(StackEmpty(asd)==true){
		printf("栈为空\n");
	}
	else{
		printf("栈非空\n");
	}
	//输出出栈序列
	while(!StackEmpty(asd)){
		Pop(asd, e);
		printf("%c ", e);
	}
	printf("\n");
	//判断栈是否为空
	if(StackEmpty(asd)==true){
		printf("栈为空\n");
	}
	else{
		printf("栈非空\n");
	}
	//释放栈 
	DestroyStack(asd);
	return 0;
}

四、涉及到栈思想的题目

P1739 表达式括号匹配

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stack>
using namespace std;
char c[1000]; 
stack<char> s;
int cnt;
int main()
{
	//输出字符串 
	scanf("%s", &c);
	for(int i=0; i<strlen(c)-1; i++){
		//如果它既不是左括号,又不是右括号,跳过
		if(c[i]!='(' && c[i]!=')'){
			continue;
		} 
		//如果是左括号(,直接入栈
		if(c[i]=='('){
			s.push('(');
		}
		else if(c[i]==')'){//如果是右括号)
			if(s.empty()){//如果栈为空,直接输出NO,结束程序
				printf("NO");
				return 0; 
			}	//注意需要先判断栈是否为空,在不空的前提下才能用top函数 
			else if(s.top()=='('){ //如果栈顶是左括号(,直接出栈
				s.pop();
			}
			else if(s.top()==')'){	//如果栈顶是右括号),直接入栈 
				s.push(')');
			}
		} 
		cnt++;
	}
	//如果栈为空,输出YES
	if(s.size()==0 && cnt!=0){
		printf("YES");
	}
	else{	//否则,输出NO 
		printf("NO");
	}
	return 0;
}

P1981 [NOIP2013 普及组] 表达式求值

#include <iostream>
#include <stack>
#include <string.h>
using namespace std;

stack<int> num;
string s;
int length;
int a[4];
int cur, before, ans;
int main()
{
	cin >> s;
	length=s.length();
	for(int i=0; i<length; ){
		//遇到数字 
		if(s[i]!='+' && s[i]!='*'){
			cur=0;
			while(s[i]>='0' && s[i]<='9'){
				cur=cur*10+s[i]-'0';
				if(cur>9999){
					cur%=10000;
				}
				++i;
			}
			num.push(cur);
		} 
		if(s[i]=='+'){
			cur=0;
			//计算加号后面的那个数
			++i;
			while(s[i]>='0' && s[i]<='9'){
				cur=cur*10+s[i]-'0';
				if(cur>9999){
					cur%=10000;
				}
				++i;
			}
			num.push(cur);
		}
		if(s[i]=='*'){
			cur=0;
			before=num.top();//取出乘号前面的那个数 
			num.pop();
			//计算乘号后面的那个数
			++i;
			while(s[i]>='0' && s[i]<='9'){
				cur=cur*10+s[i]-'0';
				if(cur>9999){
					cur%=10000;
				}
				++i;
			}
			before*=cur;
			if(before>9999){
				before%=10000;
			}
			num.push(before);
		}
	}
	while(!num.empty()){
		ans+=num.top()%10000;
		num.pop();
		ans%=100000;
	}
	if(ans<=9999){
		cout << ans;
	}
	else{
		for(int i=0; i<4; ++i){
			a[i]=ans%10;
			ans/=10;
		}
		ans=a[0]+a[1]*10+a[2]*100+a[3]*1000;
		cout << ans;
	}
	return 0;
}

P1449 后缀表达式

#include <iostream>
#include <string.h>
#include <stack>
using namespace std;

char s[1005];
int length, a, cur, before;
stack<char> opt;
stack<int> num;
int main()
{
	cin >> s;
	length=strlen(s);
	for(int i=0; i<length-1; ++i){
		if(s[i]>='0' && s[i] <='9'){
			while(s[i]!='.'){
				a=a*10+s[i]-'0';
				++i;
			}	
			num.push(a);
			a=0;
		}
		
		if(s[i]=='+'){
			cur=num.top();
			num.pop();
			before=num.top();
			num.pop();
			before+=cur;
			num.push(before);
		}
		if(s[i]=='-'){
			cur=num.top();
			num.pop();
			before=num.top();
			num.pop();
			before-=cur;
			num.push(before);
		}
		if(s[i]=='*'){
			cur=num.top();
			num.pop();
			before=num.top();
			num.pop();
			before*=cur;
			num.push(before);
		}
		if(s[i]=='/'){
			cur=num.top();
			num.pop();
			before=num.top();
			num.pop();
			before/=cur;
			num.push(before);
		}
	}
	while(!num.empty()){
		cout << num.top() << endl;
		num.pop();
	}
	return 0;
}

L2-1 彩虹瓶 (25 分)

rb.JPG

彩虹瓶的制作过程(并不)是这样的:先把一大批空瓶铺放在装填场地上,然后按照一定的顺序将每种颜色的小球均匀撒到这批瓶子里。

假设彩虹瓶里要按顺序装 N 种颜色的小球(不妨将顺序就编号为 1 到 N)。现在工厂里有每种颜色的小球各一箱,工人需要一箱一箱地将小球从工厂里搬到装填场地。如果搬来的这箱小球正好是可以装填的颜色,就直接拆箱装填;如果不是,就把箱子先码放在一个临时货架上,码放的方法就是一箱一箱堆上去。当一种颜色装填完以后,先看看货架顶端的一箱是不是下一个要装填的颜色,如果是就取下来装填,否则去工厂里再搬一箱过来。

如果工厂里发货的顺序比较好,工人就可以顺利地完成装填。例如要按顺序装填 7 种颜色,工厂按照 7、6、1、3、2、5、4 这个顺序发货,则工人先拿到 7、6 两种不能装填的颜色,将其按照 7 在下、6 在上的顺序堆在货架上;拿到 1 时可以直接装填;拿到 3 时又得临时码放在 6 号颜色箱上;拿到 2 时可以直接装填;随后从货架顶取下 3 进行装填;然后拿到 5,临时码放到 6 上面;最后取了 4 号颜色直接装填;剩下的工作就是顺序从货架上取下 5、6、7 依次装填。

但如果工厂按照 3、1、5、4、2、6、7 这个顺序发货,工人就必须要愤怒地折腾货架了,因为装填完 2 号颜色以后,不把货架上的多个箱子搬下来就拿不到 3 号箱,就不可能顺利完成任务。

输入格式:

输入首先在第一行给出 3 个正整数,分别是彩虹瓶的颜色数量 N(1<N≤10​3​​)、临时货架的容量 M(<N)、以及需要判断的发货顺序的数量 K。

随后 K 行,每行给出 N 个数字,是 1 到N 的一个排列,对应工厂的发货顺序。

一行中的数字都以空格分隔。

输出格式:

对每个发货顺序,如果工人可以愉快完工,就在一行中输出 YES;否则输出 NO

输入样例:

7 5 3
7 6 1 3 2 5 4
3 1 5 4 2 6 7
7 6 5 4 3 2 1

输出样例:

YES
NO
NO
#include <bits/stdc++.h>
using namespace std;
bool flag;
int n, m, k, cur, number;
stack<int> s;
int main()
{
	//彩虹瓶的颜色数量 N(1<N<=1000)
	//临时货架的容量 M(M<N)
	//需要判断的发货顺序的数量K。
	cin >> n >> m >> k;
	for(int i=1; i<=k; ++i){
		cur=1;
		flag=true;
		for(int j=1; j<=n; ++j){
			cin >> number;
			//如果栈顶可用,用 
			while(!s.empty() && s.top()==cur){
				cur++;
				s.pop();
			}
			if(number==cur){	//当前可用,用 
				cur++;
				//如果栈顶可用,用  
				while(!s.empty() && s.top()==cur){
					cur++;
					s.pop();
				}
			}
			else{	//不可用,放 
				s.push(number);
			}
			if(s.size()>m){	//放不下了,标记为false 
				flag=false;
			}
		}
		if(flag==false){	//放不下 
			cout << "NO" << endl;
		}
		else if(s.empty()){	//完美情况 
			cout << "YES" << endl;
		}
		else{	//栈不为空 
			cout << "NO" << endl;
		}
		while(!s.empty()){	//清空栈 
			s.pop();
		}
	}
	return 0;
}

P4387 【深基15.习9】验证栈序列

#include <bits/stdc++.h>
using namespace std;
int q, n, pushed[100010], poped[100010], pushid, asd;
stack<int> s;
int main()
{
	scanf("%d", &q);
	while(q--){
		//多测要清空 
		while(!s.empty()){
			s.pop();
		}
		scanf("%d", &n);
		//将入栈序列存下来 
		for(int i=1; i<=n; ++i){
			scanf("%d", &pushed[i]);
		}
		//将出栈序列存下来
		for(int i=1; i<=n; ++i){
			scanf("%d", &poped[i]);
		}
		asd=0;	//表示这一组测试数据入栈出栈匹配的数量 
		s.push(pushed[1]);	//将入栈序列中的第一个数入栈 
		pushid=2;			//待入栈序号赋值为2 
		for(int i=1; i<=n; ++i){	//枚举出栈序列 
			//栈不为空, 并且栈顶元素恰好等于出栈序列中的数 
			if(!s.empty() && poped[i]==s.top()){
				s.pop();	//出栈 
				asd++;		//出栈匹配数加一 
				if(asd==n){	//如果匹配数恰好等于n, 说明完全匹配 
					printf("Yes\n");
					break;	
				}
			}
			else{	//栈为空或者栈顶元素不等于出栈序列中的数 
				if(pushid>n){	//入栈序列中的元素已经全部入栈 
					//此时由于出栈序列中还有元素, 所以不可能匹配成功 
					printf("No\n");
					break;
				}
				s.push(pushed[pushid]);		//入栈 
				pushid++;
				i--;	//与for循环++i相抵消, 保持出栈序列的序号不变 
			}
		}
	}
	return 0;
}

//TODO

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ypeijasd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值