C++数据结构之单调栈

定义

单调栈(Monotone Stack):一种特殊的栈。在栈的「先进后出」规则基础上,要求「从 栈顶栈底 的元素是单调递增(或者单调递减)」。其中满足从栈顶到栈底的元素是单调递增的栈,叫做「单调递增栈」。满足从栈顶到栈底的元素是单调递减的栈,叫做「单调递减栈」。

这里是以栈顶到栈底的顺序为基准来描述单调栈。

1. 基础
1.1单调递增栈

单调递增栈:只有比栈顶元素小的元素才能直接进栈,否则需要先将栈中比当前元素小的元素出栈,再将当前元素入栈。

这样就保证了:栈中保留的都是比当前入栈元素大的值,并且从栈顶到栈底的元素值是单调递增的。

经常出现的考题如下,模拟数组[2, 7, 5, 4, 6, 3, 4, 2]在单调递增栈的进栈、出栈过程。

第 i 步待插入元素操 作结 果(左侧为栈底)作 用
122 入栈[2]元素 2 的左侧无比 2 大的元素
272 出栈,7 入栈[7]元素 7 的左侧无比 7 大的元素
355 入栈[7, 5]元素 5 的左侧第一个比 5 大的元素为:7
444 入栈[7, 5, 4]元素 4 的左侧第一个比 4 大的元素为:5
564 出栈,5 出栈,6 入栈[7, 6]元素 6 的左侧第一个比 6 大的元素为:7
633 入栈[7, 6, 3]元素 3 的左侧第一个比 3 大的元素为:6
743 出栈,4 入栈[7, 6, 4]元素 4 的左侧第一个比 4 大的元素为:6
822 入栈[7, 6, 4, 2]元素 2 的左侧第一个比 2 大的元素为:4
1.2 单调递减栈

单调递减栈:只有比栈顶元素大的元素才能直接进栈,否则需要先将栈中比当前元素大的元素出栈,再将当前元素入栈。

这样就保证了:栈中保留的都是比当前入栈元素小的值,并且从栈顶到栈底的元素值是单调递减的。

这里同样以[4, 3, 2, 5, 7, 4, 6, 8]为例

第 i 步待插入元素操 作结 果(左侧为栈底)作用
144 入栈[4]元素 4 的左侧无比 4 小的元素
234 出栈,3 入栈[3]元素 3 的左侧无比 3 小的元素
323 出栈,2 入栈[2]元素 2 的左侧无比 2 小的元素
455 入栈[2, 5]元素 5 的左侧第一个比 5 小的元素是:2
577 入栈[2, 5, 7]元素 7 的左侧第一个比 7 小的元素是:5
647 出栈,5 出栈,4 入栈[2, 4]元素 4 的左侧第一个比 4 小的元素是:2
766 入栈[2, 4, 6]元素 6 的左侧第一个比 6 小的元素是:4
888 入栈[2, 4, 6, 8]元素 8 的左侧第一个比 8 小的元素是:6

单调栈的适用场景

单调栈可以在时间复杂度为 O(n) 的情况下,求解出某个元素左边或者右边第一个比它大或者小的元素。

所以单调栈一般用于解决一下几种问题:

  • 寻找左侧第一个比当前元素大的元素。
  • 寻找左侧第一个比当前元素小的元素。
  • 寻找右侧第一个比当前元素大的元素。
  • 寻找右侧第一个比当前元素小的元素。

上边的分类解法有点绕口,可以简单记为以下条规则:

  • 无论哪种题型,都建议从左到右遍历元素。
  • 查找 「比当前元素大的元素」 就用 单调递增栈,查找 「比当前元素小的元素」 就用 单调递减栈
  • 「左侧」 查找就看 「插入栈」 时的栈顶元素,从 「右侧」 查找就看 「弹出栈」 时即将插入的元素。

单调栈模板

单调递增栈
//单调递增栈
template<typename T>
void IncStack(stack<T>& s,const vector<T> &nums) {
	for (auto it = nums.begin(); it != nums.end(); it++) {
		while (!s.empty() && s.top() <= *it) {
			s.pop();
		}
		s.push(*it);
	}
}

这个模板是将数组转化成单调递增栈。

单调递减栈
//单调递减栈
template<typename T>
void DecStack(stack<T>& s, const vector<T>& nums) {
	for (auto it = nums.begin(); it != nums.end(); it++) {
		while (!s.empty() && s.top() >= *it) {
			s.pop();
		}
		s.push(*it);
	}
}

老规矩,有用二连,感谢大家!

  • 9
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言中的数据结构顺序栈是一种使用数组来实现的栈结构。顺序栈的特点是先进后出,即最后进入的元素最先出栈。顺序栈可以通过数组的下标来实现元素的进栈和出栈操作。 在C语言中,可以通过定义一个数组和一个栈顶指针来实现顺序栈。栈顶指针指向栈中最后一个元素的位置。当栈为空时,栈顶指针指向-1。 以下是一种实现顺序栈的代码示例: ```c #define MAX_SIZE 100 // 定义栈的最大容量 typedef struct { int data[MAX_SIZE]; // 用数组存储栈元素 int top; // 栈顶指针 } SeqStack; void InitStack(SeqStack *s) { s->top = -1; // 初始化栈顶指针为-1,表示栈为空 } int IsEmpty(SeqStack *s) { return s->top == -1; // 判断栈是否为空 } int IsFull(SeqStack *s) { return s->top == MAX_SIZE - 1; // 判断栈是否已满 } void Push(SeqStack *s, int element) { if (IsFull(s)) { printf("Stack is full.\n"); // 栈已满,无法继续入栈 return; } s->top++; // 栈顶指针加1 s->data[s->top = element; // 元素入栈 } int Pop(SeqStack *s) { if (IsEmpty(s)) { printf("Stack is empty.\n"); // 栈为空,无法进行出栈操作 return -1; } int element = s->data[s->top]; // 获取栈顶元素 s->top--; // 栈顶指针减1 return element; } int GetTop(SeqStack *s) { if (IsEmpty(s)) { printf("Stack is empty.\n"); // 栈为空,无法获取栈顶元素 return -1; } return s->data[s->top]; // 返回栈顶元素 } ``` 以上是一个简单的C语言实现顺序栈的代码示例。通过调用相应的函数,可以实现顺序栈的初始化、判断栈是否为空、判断栈是否已满、元素入栈、元素出栈、获取栈顶元素等操作。需要注意的是,在使用顺序栈时,需要注意栈的容量是否足够,以避免栈溢出的情况发生。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值