基础数据结构—栈

1.定义

栈是常用的一种线性数据结构。请注意,本文主要讲的是栈这种数据结构,而非程序运行时的系统栈/栈空间。
栈的修改与访问是按照后进先出的原则进行的,因此栈通常被称为是后进先出(last in first out)表,简称 LIFO 表。
栈(stack),它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。

2. STL中的栈

C++ 中的 STL 也提供了一个容器 std::stack,使用前需要引入 stack 头文件。

// clang-format off
template<
    class T,
    class Container = std::deque<T>
> class stack;

Tstack 中要存储的数据类型。

Container 为用于存储元素的底层容器类型。这个容器必须提供通常语义的下列函数:

  • back()
  • push_back()
  • pop_back()

STL 容器 std::vectorstd::dequestd::list 满足这些要求。如果不指定,则默认使用 std::deque 作为底层容器。
STL 中的 stack 容器提供了一众成员函数以供调用,其中较为常用的有:

  • 元素访问
    • st.top() 返回栈顶
  • 修改
    • st.push() 插入传入的参数到栈顶
    • st.pop() 弹出栈顶
  • 容量
    • st.empty() 返回是否为空
    • st.size() 返回元素数量

其实也可以用数组模拟栈:

int st[N];
// 这里使用 st[0] (即 *st) 代表栈中元素数量,同时也是栈顶下标

// 压栈 :
st[++*st] = var1;
// 取栈顶 :
int u = st[*st];
// 弹栈 :注意越界问题, *st == 0 时不能继续弹出
if (*st) --*st;
// 清空栈
*st = 0;

反正能把题目做出来就行 =。=

3. 算法题

3.1 验证栈序列

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

题目描述:
给出两个序列 pushedpoped 两个序列,其取值从 1n (n ≤ 100000)。已知入栈序列是 pushed,如果出栈序列有可能是 poped,则输出 Yes,否则输出 No。为了防止骗分,每个测试点有多组数据,不超过 5 组。

输入格式:
第一行一个整数 q,询问次数。
接下来 q个询问,对于每个询问:
第一行一个整数 n 表示序列长度;
第二行 n 个整数表示入栈序列;
第三行 n 个整数表示出栈序列;

输出格式:
对于每个询问输出答案。

输入输出样例:
输入 #1

2
5
1 2 3 4 5
5 4 3 2 1
4
1 2 3 4
2 4 1 3

输出 #1

Yes
No

对于这个题目而言,解决思路就是查看入栈序列的栈顶,然后和出栈序列比较,看看能不能被顺利出栈。如果当前的栈顶元素等于出栈序列的元素,那么就把这个元素弹栈,否则继续入栈,直到和入栈元素全部比较完成。如果比较完,栈内元素为空,就说明入栈元素可以按照下面的顺序弹栈,否则就不能。
在这里插入图片描述
具体流程如下:
在这里插入图片描述
这里解释一下,因为题目给的是一个具体的入栈和出栈序列,并不是真正的栈,所以我们要引入一个新栈,也可以理解为临时栈,通过这个临时栈可以知道入栈序列是否可以通过下面的出栈序列出栈。在判断栈是否为空的时候要注意使用循环判断,因为栈可以循环出栈,就像是第一个测试集一样。
下面给出AC代码:

#include<bits/stdc++.h>
using namespace std;
int a[100005];
int b[100005];
stack<int> s;
int main()
{
	int q;
	int n;
	cin>>q;
	while(q--)
	{
		//清空 
		while(s.empty()==0)
		{
			s.pop();
		}
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];	
		}
		for(int i=1;i<=n;i++)
		{
			cin>>b[i];	
		}
		int j=1;	//当前栈顶元素为应该出栈的b[i] 
		for(int i=1;i<=n;i++)
		{
			s.push(a[i]);
			while(s.top()==b[j])
			{
				s.pop();
				j++;
				if(s.empty()==1)
				{
					break;
				}
			}
		}
		if(s.empty()==1)
			cout<<"Yes"<<endl;
		else
			cout<<"No"<<endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值