栈和队列是STL(C++标准库)里面的两个数据结构
栈提供push和pop等接口,所有元素必须符合先进后出规则,所以栈不提供走访功能,也不提供迭代器(iterator)。不像是set或者map提供迭代器iterator来遍历所有元素。
栈是以底层容器完成其所有的工作,对外提供统一的接口,底层容器是可插拔的(可以控制使用哪种容器来实现栈的功能)。
STL中栈往往不被归类为容器,而被归类为container adapter(容器适配器)。
STL中栈是用什么容器实现的?
栈的底层实现可以是vector,deque,list都是可以的,主要就是数组和链表的底层实现。
我们常用的SGI STL,如果没有指定底层实现的话,默认是以deque为缺省情况下栈的底层结构。
deque是一个双向队列,只要封住一段,只开通另一端就可以实现栈的逻辑了。
SGI STL中 队列底层实现缺省情况下一样使用deque实现的。
也可以指定vector为栈的底层实现,初始化语句如下:
std::stack<int,std::vector<int>> third;//使用vector为底层容器的栈
队列也是一样的,先进先出的数据结构,同样不允许有遍历行为,不提供迭代器,SGI STL中队列一样是以deque为缺省情况下的底部结构。
也可以指定list为起底层实现,初始化queue的语句如下:
std::queue<int, std::list<int>>third;//定义以list为底层容器的队列
所以STL 队列也不被归类为容器,而被归类为container adapter(容器适配器)
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push
、pop
、peek
、empty
):
实现 MyQueue
类:
void push(int x)
将元素 x 推到队列的末尾int pop()
从队列的开头移除并返回元素int peek()
返回队列开头的元素boolean empty()
如果队列为空,返回true
;否则,返回false
注意:
1.栈为空才能入栈,栈不为空才能出栈
2.栈先获取top元素,再pop弹出
class MyQueue {
public:
//设置两个栈
stack<int> stIn;
stack<int> stOut;
MyQueue() {
}
void push(int x) {
//直接入栈
stIn.push(x);
}
int pop() {
//只有stOut为空,才能入栈
if (stOut.empty()) {
while(!stIn.empty()) {
stOut.push(stIn.top());
stIn.pop();//入栈后弹出顶部元素
}
}
int result = stOut.top();//先保存顶部元素
stOut.pop();//再弹出
return result;
}
int peek() {
int res = this->pop();//直接使用已有的pop函数
stOut.push(res);//因为pop()弹出了res,所以再添加回去
return res;
}
bool empty() {
return stIn.empty() && stOut.empty();
}
};
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push
、top
、pop
和 empty
)。
实现 MyStack
类:
void push(int x)
将元素 x 压入栈顶。int pop()
移除并返回栈顶元素。int top()
返回栈顶元素。boolean empty()
如果栈是空的,返回true
;否则,返回false
。
主要是pop()
1.记录size,保留que1一个元素,在它前面的所有元素移动到que2
2.result获取que1这个元素,弹出
3.que1=que2,清空que2
class MyStack {
public:
//定义两个队列
queue<int> que1;
queue<int> que2;
MyStack() {
}
void push(int x) {
que1.push(x);
}
int pop() {
//que1保留一个元素,将在这个元素前面的其他元素全部移动到que2
//结果获取这个元素,que1弹出
//que1=que2,清空que2
int size = que1.size();
size--;
while(size--) {
que2.push(que1.front());
que1.pop();
}
int result = que1.front();
que1.pop();
que1 = que2;
while(!que2.empty()) {
que2.pop();
}
return result;
}
int top() {
return que1.back();
}
bool empty() {
return que1.empty();
}
};
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
三种情况:
1.遍历字符串匹配的过程中,栈已经空了,没有匹配的字符了
2.遍历字符串匹配的过程中,不相符
3.遍历完成后,还有剩余
技巧:遇到([{,入栈右括号,直接用右括号进行匹配即可。
class Solution {
public:
bool isValid(string s) {
if (s.size() % 2 != 0) return false;
stack<char> st;
//遍历
for (int i = 0; i < s.size(); i++) {
if (s[i] == '(') st.push(')');
else if (s[i] == '[') st.push(']');
else if (s[i] == '{') st.push('}');
//三种情况:遍历字符串匹配的过程中,栈已经空了,没有匹配的字符了
//遍历字符串匹配的过程中,不相符
//遍历完成后,栈还有剩余
else if (st.empty() || st.top() != s[i]) return false;
else st.pop();//st.top()和s[i]相等,弹出元素
}
//遍历完成后,如果还有剩余就不是空,说明返回false
return st.empty();
}
};
给出由小写字母组成的字符串 S
,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
遍历字符串,如果栈为空或者字符和栈顶元素不相等,入栈;否则,重复则弹出;
弹出并收集栈中所有字符,翻转;
class Solution {
public:
string removeDuplicates(string s) {
//遍历字符串,如果为空或者字符和栈中不相等,入栈;否则相等,弹出
//遍历完成后,弹出栈中内容,并翻转
stack<char> st;
for (char s : s) {
if (st.empty() || s != st.top()) {
st.push(s);
}else {
st.pop();
}
}
string result = "";
while(! st.empty()) {
result += st.top();
st.pop();
}
reverse (result.begin(), result.end());
return result;
}
};
给你一个字符串数组 tokens
,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
- 有效的算符为
'+'
、'-'
、'*'
和'/'
。 - 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
- 两个整数之间的除法总是 向零截断 。
- 表达式中不含除零运算。
- 输入是一个根据逆波兰表示法表示的算术表达式。
- 答案及所有中间计算结果可以用 32 位 整数表示。
遇到数字入栈,遇到运算符取栈顶两元素计算,计算结果入栈。
class Solution {
public:
int evalRPN(vector<string>& tokens) {
//遇到数字入栈,遇到运算符取栈顶两元素计算,计算结果入栈
stack<long long> st;
for (int i = 0; i < tokens.size(); i++) {
if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/") {
//取栈顶两元素
long long num1 = st.top();
st.pop();
long long num2 = st.top();
st.pop();
if (tokens[i] == "+") st.push(num2 + num1);
if (tokens[i] == "-") st.push(num2 - num1);
if (tokens[i] == "*") st.push(num2 * num1);
if (tokens[i] == "/") st.push(num2 / num1);
}else {
st.push(stoll(tokens[i]));
}
}
char result = st.top();
st.pop();
return result;
}
};