介绍

栈和队列是STL(C++标准库)里面的两个数据结构。

  • HP STL 其他版本的C++ STL,一般是以HP STL为蓝本实现出来的,HP STL是C++ STL的第一个实现版本,而且开放源代码。
  • P.J.Plauger STL 由P.J.Plauger参照HP STL实现出来的,被Visual C++编译器所采用,不是开源的。

  • SGI STL 由Silicon Graphics Computer Systems公司参照HP STL实现,被Linux的C++编译器GCC所采用,SGI STL是开源软件,源码可读性甚高。

栈和队列也是SGI STL里面的数据结构

stack

  • push(): 在栈顶添加一个元素。
  • pop(): 移除栈顶元素。
  • top(): 返回栈顶元素的引用,但不移除它。
  • empty():检查栈是否为空。
  • size(): 返回栈中元素的数量。

queue

  • empty(): 检查队列是否为空。
  • size(): 返回队列中的元素数量。
  • front(): 返回队首元素的引用。
  • back(): 返回队尾元素的引用。
  • push(): 在队尾添加一个元素。
  • pop(): 移除队首元素。

232.用栈实现队列

题目链接
状态:基本功

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
class MyQueue {
public:
stack<int> sin;
stack<int> sout;
MyQueue() {

}

void push(int x) {
sin.push(x);
}

int pop() {
if(sout.empty()){
while(!sin.empty()){
sout.push(sin.top());
sin.pop();
}
}
int t=sout.top();
sout.pop();
return t;

}

int peek() {
int x=pop();
sout.push(x);
return x;
}

bool empty() {
return sin.empty()&&sout.empty();
}
};

225. 用队列实现栈

题目链接
状态:基本功

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
class MyStack {
public:
queue<int> q;
MyStack() {

}

void push(int x) {
q.push(x);

}

int pop() {
int n=q.size()-1;
while(n--){
q.push(q.front());
q.pop();
}
int t=q.front();
q.pop();
return t;

}

int top() {
return q.back();

}

bool empty() {
return q.empty();

}
};

20. 有效的括号

题目链接
状态:错一次
错误原因:匹配前未检查栈是否为空

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public:
bool isValid(string s) {
int n = s.size();
if (n % 2 != 0)
return false;
stack<char> st;
char t;
for (char i : s) {
if (i == '(' || i == '[' || i == '{')
st.push(i);
else if (!st.empty() && ((i == ')' && st.top() == '(') ||
(i == ']' && st.top() == '[') ||
(i == '}' && st.top() == '{'))) {
st.pop();
} else
return false;
}
return st.empty();
}
};

改进版本
见前括号,push相应的后括号,然后匹配时直接对比是否相同(其实思路一样)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public:
bool isValid(string s) {
if (s.size() % 2 != 0) return false; // 如果s的长度为奇数,一定不符合要求
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(']');
// 第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号 return false
// 第二种情况:遍历字符串匹配的过程中,发现栈里没有我们要匹配的字符。所以return false
else if (st.empty() || st.top() != s[i]) return false;
else st.pop(); // st.top() 与 s[i]相等,栈弹出元素
}
// 第一种情况:此时我们已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false,否则就return true
return st.empty();
}
};

1047. 删除字符串中的所有相邻重复项

题目链接
状态:错一次
错误原因:reverse参数写错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public:
string removeDuplicates(string s) {
stack<char> st;
for (char i : s) {
if (st.empty()) {
st.push(i);
} else if (st.top() != i) {
st.push(i);
} else if (!st.empty() || st.top() == i) {
st.pop();
}
}
string ans = "";
while (!st.empty()) {
ans += st.top();
st.pop();
}
reverse(ans.begin(), ans.end());
return ans;
}
};

官解:直接拿字符串当栈!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public:
string removeDuplicates(string S) {
string result;
for(char s : S) {
if(result.empty() || result.back() != s) {
result.push_back(s);
}
else {
result.pop_back();
}
}
return result;
}
};