栈是一种先进后出的数据结构,你可以把栈想象成一个羽毛球筒子。先放的,反而会在底下,后方的则在上面。

栈的实现方法

手写栈

我们设置一个指针 \(top\) 表示当前的栈顶下标,用一个数组 \(a\) 来模拟栈。

入栈

当一个元素入栈时,\(top\) 加1, \(a_{top}\) 为入栈元素。

void push(int x){
  top++;
  a[top] = x;
}

出栈

当一个元素出栈时,\(top\) 减1。

void pop(){
  top--;
}

获取栈顶元素

返回 \(a_{top}\) 即可.

int top(){
  return a[top];
}

判断栈是否为空

\(top\)\(0\) 时,说明栈是空的。

bool isEmpty(){
  return !top;
}

获取栈元素数量

输出 \(top\) 即可。

int size(){
  return top;
}

/注意,这些函数有些为重名,不要照搬。

STL函数大法

看到上面的一大堆代码,是不是感觉很烦,其实呢,c++给我们内置了栈这种数据结构。

stack<int>a; //初始化栈,int可以替换成char, vector<int>, string, pair<int,int>等
a.push(x); // 将x入栈
a.pop(x); // 弹出栈顶元素
a.size(); // 获取元素数量
a.top(); // 获取栈顶元素

写到这,作者不禁从内心赞美STL的好啊!

来道例题

大家都看到这里了,可能有些人都不知道栈有什么用,我接下来带大家做几道例题来认识一下吧!

P1739 表达式括号匹配

先看描述:

假设一个表达式有英文字母(小写)、运算符(+​、-​、*​、/​)和左右小(圆)括号构成,以 @​ 作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则输出 YES​;否则输出 NO​。表达式长度小于 \(255\),左圆括号少于 \(20\) 个。

很明显,我们需要检查括号是否匹配,我们可以分几种类型来讨论:

  • ()​这种很明显是合法的。

  • (())​这种很明显也是合法的。

  • ([)]​这种很明显不合法。

我们发现,括号遵守就近匹配原则,也就是最近的一个左括号匹配到最近的一个右括号。这不正好匹配栈的特性吗!所以这道题很明显要用栈来做。

#include <bits/stdc++.h>
using namespace std;
stack<char>charList; // 初始化一个char类型的栈
char temp;
int main(){
	 while(temp!='@'){
	 	cin>>temp;
	 	if(temp=='('){
	 		charList.push(temp);
		}
		if(temp==')'){
			if(charList.size()<=0){ // 如果所有的括号都匹配完了,还有左括号待匹配的话,说明
				cout<<"NO"<<endl;    // 该表达式不合法。
				return 0;
			}
			else{
				 charList.pop(); // 匹配成功,弹出。
			}
		}
	 }
	if(charList.size()==0){
		cout<<"YES"<<endl; // 栈空,说明全部匹配,表达式合法。
		return 0;
	}
	cout<<"NO";
}

单调栈

单调栈是栈的一种变种,单调栈中的元素始终是递增的。

让我们模拟一遍单调栈的运行过程,这里的单调栈是单调递增栈。

   我们现在有 6 个数 5,2,3,4,1,6

   首先我们要明白,我们存放的是下标。然后,我们直接把元素放在栈顶,会破坏它的单调性。所以我们需要吐出栈顶的元素,使得我们当前的元素再加进去不会破坏它的单调性。
  1. 我们当前栈内没有元素,将 5 加入。现在栈内元素应该是 1。
  2. 当前元素为 2,我们发现加入之后不能单调,于是吐出 5,加入 2。当前栈内元素为 2。
  3. 接下来是 3,4。我们发现加入不会破坏单调性,于是直接加入,栈内元素 2,3,4。
  4. 遇到 1,只能吐出栈内所有元素,加入 1。
  5. 最后加入 6。整个算法流程完成。

实现

#include<stack>
using namespace std;
int n,a[3000005],f[3000005];
stack<int>s;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=n;i>=1;i--)
	{
		while(!s.empty()&&a[s.top()]<=a[i]) s.pop(); // 弹出到不破坏单调性为止。
		f[i]=s.empty()?0:s.top(); // 如果栈空,输出0。否则输出栈顶。
		s.push(i); // 入栈
	}
	for(int i=1;i<=n;i++) cout << f[i] << ' ';
	return 0;
}
posted @ 2025-07-11 23:39  fyv233  阅读(10)  评论(0)    收藏  举报