栈:后入先出的数据结构 在 LIFO 数据结构中,将首先处理添加到队列中的最新元素。
与队列不同,栈是一个 LIFO 数据结构。通常,插入操作在栈中被称作入栈 push。与队列类似,总是在堆栈的末尾添加一个新元素。但是,删除操作,退栈 pop,将始终删除队列中相对于它的最后一个元素。
栈-实现 栈的实现比队列容易。动态数组足以实现堆栈结构。以下提供一个简单的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include <iostream> class MyStack { private : vector <int > data; public : void push (int x) { data.push_back(x); } bool isEmpty () { return data.empty(); } int top () { return data.back(); } bool pop () { if (isEmpty()) { return false ; } data.pop_back(); return true ; } }; int main () { MyStack s; s.push(1 ); s.push(2 ); s.push(3 ); for (int i = 0 ; i < 4 ; ++i) { if (!s.isEmpty()) { cout << s.top() << endl ; } cout << (s.pop() ? "true" : "false" ) << endl ; } }
栈-用法 大多流行语言都提供了内置的栈库。所以不必重复造轮子。 除了初始化 ,我们还需要知道如何使用两个最重要的操作:入栈 和退栈 。除此之外,还应该能够从栈中获得顶部元素 。
下面是代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostream> int main () { stack <int > s; s.push(5 ); s.push(13 ); s.push(8 ); s.push(6 ); if (s.empty()) { cout << "Stack is empty!" << endl ; return 0 ; } s.pop(); cout << "The top element is: " << s.top() << endl ; cout << "The size is: " << s.size() << endl ; }
当你想首先处理最后一个元素的时候,栈将是最合适的数据操作。
题目:最小栈 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。
push(x):将元素 x 推入栈中。 pop():删除栈顶的元素。 top():获取栈顶元素。 getMin():检索栈中的最小元素。 官方思路 如下
方法一:使用辅助栈
定义一个[数据栈]来支持 push、pop、top 操作 定义一个[辅助栈]其栈顶为当前最小值,以支持常数时间复杂度的 getMin 操作 代码如下(C++):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class MinStack { stack <int > dataStack,minStack; public : MinStack() { minStack.push(INT_MAX); } void push (int x) { dataStack.push(x); if (minStack.empty() || x <= minStack.top()){ minStack.push(x); } } void pop () { if (!dataStack.empty()){ if (dataStack.top() == minStack.top()){ minStack.pop(); } dataStack.pop(); } } int top () { return dataStack.top(); } int getMin () { return minStack.top(); } };
时间复杂度 O(1),空间复杂度 O(n)。
方法二:使用 Stack<Node> 除了保存当前值外,额外保存当前最小值。
方法三:自定义 Stack,以单链表形式自定义栈。
题目:有效的括号 这个题是我觉得比较简单的了。开心。
给定一个只包括’(‘,’)’,’{‘,’}’,’[‘,’]‘的字符串,判断字符串是否有效。 有效字符串需满足:
左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 注意空字符串可被认为是有效字符串。
代码实现如下(C++):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution {public : bool isValid (string s) { stack <char > st; for (auto x:s){ if (x == '(' || x == '[' || x == '{' ) st.push(x); else { if (st.empty()) return false ; if ((x == ')' && st.top() == '(' ) || (x == ']' && st.top() == '[' ) || (x == '}' && st.top() == '{' )) st.pop(); else return false ; } } if (st.empty()) return true ; else return false ; } };
算法过程:初始化栈。
一次处理表达式的每个括号。 如果遇到开括号,我们只需将其推到栈上即可。这意味着我们将稍后处理它,让我们简单地转到前面的 子表达式。 如果我们遇到一个闭括号,那么我们检查栈顶的元素。如果栈顶的元素是一个 相同类型的 左括号,那么我们将它从栈中弹出并继续处理。否则,这意味着表达式无效。 如果到最后我们剩下的栈中仍然有元素,那么这意味着表达式无效。 题目:每日温度 请根据每日气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。
例如,给定一个列表 temperatures=[73,74,75,71,69,72,76,73],你的输出应该是[1,1,4,2,1,1,0,0]。 提示:气温列表长度的范围是[1,30000]。每个气温的值的均为华氏度,都是在[30,100]范围内的整数。
代码如下(C++):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution {public : vector <int > dailyTemperatures (vector <int >& T) { int n = T.size(); vector <int > ans (n) ; stack <int > s; for (int i = 0 ; i < n; i++) { while (!s.empty() && T[i] > T[s.top()]) { int previousIndex = s.top(); ans[previousIndex] = i - previousIndex; s.pop(); } s.push(i); } return ans; } };
逆波兰表达式求值 根据逆波兰表示法,求表达式的值。 有效的运算符包括+,-,*,/。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明:
整数除法只保留整数部分。 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。 示例 1:
1 2 3 输入:["2","1","+","3","*"] 输出:9 解释:该算式转化为常见的中缀算术表达式为:((2+1)*3)=9
代码如下(C++):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class Solution {public : int ans; int evalRPN (vector <string >& tokens) { stack <int > st; int ans_1,ans_2; for (auto v_mate : tokens){ if (v_mate == "+" ){ ans_1 = st.top(); st.pop(); ans_2 = st.top(); st.pop(); st.push(ans_2 + ans_1); } else if (v_mate == "-" ){ ans_1 = st.top(); st.pop(); ans_2 = st.top(); st.pop(); st.push(ans_2 - ans_1); } else if (v_mate == "*" ){ ans_1 = st.top(); st.pop(); ans_2 = st.top(); st.pop(); st.push(ans_2 * ans_1); } else if (v_mate == "/" ){ ans_1 = st.top(); st.pop(); ans_2 = st.top(); st.pop(); st.push(ans_2 / ans_1); } else { st.push(atoi(v_mate.c_str())); } } ans = st.top(); return ans; } };
具体解释见注释。
声明:本文为学习记录,参考之处较多,如果有侵权内容,请联系我立即删除 。