栈与队列相关题型
基础知识
栈
栈:后进先出(LIFO-last in first out):最后插入的元素最先出来。
使用栈,要先包含头文件 : #include
定义栈,以如下形式实现: stack s; 其中Type为数据类型(如 int,float,char等)。
栈的主要操作:
s.push(item); //将item压入栈顶
s.pop(); //删除栈顶的元素,但不会返回
s.top(); //返回栈顶的元素,但不会删除
s.size(); //返回栈中元素的个数
s.empty(); //检查栈是否为空,如果为空返回true,否则返回false
//栈操作举例:
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
void main()
{
stack<int> s;
int num;
cout<<"------Test for Stack-------"<<endl;
cout<<"Input number:"<<endl;
while(cin>>num)
{
s.push(num);
}
cout<<"The Stack has "<<s.size()<<" numbers.They are:"<<endl;
while(!s.empty())
{
cout<<s.top()<<" ";
s.pop();
}
cout<<"\nNow the size is "<<s.size()<<endl;
system("Pause");
}
运行截图
队列
队列:先进先出(FIFO-first in first out):最先插入的元素最先出来。
使用队列,要先包含头文件 : #include
定义队列,以如下形式实现: queue q; 其中Type为数据类型(如 int,float,char等)。
队列的主要操作:
q.push(item) //将item压入队列尾部
q.pop() //删除队首元素,但不返回
q.front() //返回队首元素,但不删除
q.back() //返回队尾元素,但不删除
q.size() //返回队列中元素的个数
q.empty() //检查队列是否为空,如果为空返回true,否则返回false
//队列操作举例
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
void main()
{
queue<int> q;
int num;
cout<<"------Test for Queue-------"<<endl;
cout<<"Input number:"<<endl;
while(cin>>num)
{
q.push(num);
}
cout<<"Now the Queue has "<<q.size()<<" numbers."<<endl;
cout<<"The first is "<<q.front()<<endl;
cout<<"The last is "<<q.back()<<endl;
cout<<"All numbers:"<<endl;
while(!q.empty())
{
cout<<q.front()<<" ";
q.pop();
}
cout<<"Now the Queue has "<<q.size()<<" numbers."<<endl;
system("Pause");
}
运行截图
栈与队列的区别
7-3 银行业务队列简单模拟
https://pintia.cn/problem-sets/1628020702584594432/exam/problems/1628020809572896770
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
int a[N],cnt;
int main() {
queue<int> A;
queue<int> B;
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
int data;
cin >> data;
// !(data & 1):即data 为偶数 等同于 data % 2 == 0
if (!(data & 1)) B.push(data);
else A.push(data);
}
while (A.size() && B.size()) {
if (A.size() >= 2) {
a[cnt++] = A.front();
A.pop();
a[cnt++] = A.front();
A.pop();
}// A窗口处理速度是B窗口的两倍
else {
a[cnt++] = A.front();
A.pop();
}
a[cnt++] = B.front();
B.pop();
}
// B窗口无人,A窗口有人的情况
while (A.size()) {
a[cnt++] = A.front();
A.pop();
}
// A窗口无人,B窗口有人的情况
while (B.size()) {
a[cnt++] = B.front();
B.pop();
}
for (int i = 0; i < cnt; i++) {
if (i != cnt - 1) cout << a[i] << " ";
else cout << a[i];
}
}
7-4 表达式转换
https://pintia.cn/problem-sets/1628020702584594432/exam/problems/1628020809572896771
#include<bits/stdc++.h>
using namespace std;
int main() {
string s;
cin >> s;
stack<char> sk;// 用来存储运算符
bool flag = true;//作为一个标志,表示字符一定为数字
for (int i = 0; i < (int)s.size(); i++) {
if (isdigit(s[i])) {// isdigit 函数:用来判断字符是否为数字
if (flag) {
cout << s[i];
flag = false;
continue;
}
if (!isdigit(s[i-1])) {
cout << " " << s[i];
}
else if (isdigit(s[i-1]) || isdigit(s[i+1])) cout << s[i];
}
else if (sk.empty()) {
if (s[i] == '+' && i == 0) continue; //+25
else if (s[i] == '-' && i == 0) {// -25
cout << s[i];
flag = true;// 表示当前字符的下一个字符一定是数字
continue;
}
else if (s[i] == '.') { //2.5
cout << s[i];
flag = true;// 当前字符的下一个字符一定为数字
continue;
}
sk.push(s[i]);
}
else if (s[i] == '*' || s[i] == '/') {
// 运算符高于栈顶元素,直接加入栈
if (sk.top() == '+' || sk.top() == '-' || sk.top() == '(') sk.push(s[i]);
else {// 否则说明当前字符运算符级别与栈顶元素级别相同
if (i) cout << " ";
cout << s[i];
}
}
else if (s[i] == '+' || s[i] == '-') {
if (s[i-1] == '(' && s[i] == '+') continue; // (+25)
else if (s[i-1] == '(') {// (-25)
cout << s[i];
flag = true;
continue;
}
// 栈顶元素运算级别大于当前符号级别,输出栈顶元素
while (!sk.empty() && (sk.top() == '*' || sk.top() == '/')) {
if (i) cout << " ";
cout << sk.top();
sk.pop();
}
if (sk.empty() || sk.top() == '(') sk.push(s[i]); // 栈内无元素的情况
else {
if (i) cout << " ";
cout << s[i];
}
}
else if (s[i] == '(') sk.push(s[i]);
else if (s[i] == ')') {
while (sk.top() != '(') {
if (i) cout << " ";
cout << sk.top();
sk.pop();
}
sk.pop(); // 弹出'('
}
else if (s[i] == '.') {
cout << s[i];
flag = true; // 2.5
}
}
// 如果栈内还有元素,直接输出即可
while (sk.size()) {
cout << " " << sk.top();
sk.pop();
}
}
扩展:中缀转前缀思路
*(1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
* (2) 从右至左扫描中缀表达式;
* (3) 遇到操作数时,将其压入S2;
* (4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
* (4-1) 如果S1为空,则直接将此运算符入栈;
* (4-2) 否则,若优先级比栈顶运算符的较高或相等(后缀表达式中是较高,没有相等)或栈顶运算符为右括号“)”,
也将运算符压入S1;
* (4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;
* (5) 遇到括号时:
* (5-1) 如果是右括号“)”,则直接压入S1;
* (5-2) 如果是左括号“(”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到右括号为止,此时将这一对括号丢弃
* (6) 重复步骤(2)至(5),直到表达式的最左边;
* (7) 将S1中剩余的运算符依次弹出并压入S2;
* (8) 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。
7-58 堆栈模拟队列
https://pintia.cn/problem-sets/1628020702584594432/exam/problems/1628020809572896825
#include<bits/stdc++.h>
using namespace std;
int main() {
int n,m;
cin >> n >> m;
stack<int> s1,s2;
if (n < m) swap(n,m);
// 默认将s1设置为大容量的栈(容量为n),s2设置为小容量的栈(容量为m)
char c;
while (cin >> c) {
if (c == 'T') break;
else if (c == 'A') {
int data;
cin >> data;
if ((int)s2.size() < m) s2.push(data);
else {
if (s1.empty()) {
while (s2.size()) {
s1.push(s2.top());
s2.pop();
}
s2.push(data);
}
else cout << "ERROR:Full" << '\n';
}
}
else {
if (s1.size()) {
cout <<s1.top() << '\n';
s1.pop();
}
else {
if(s2.size()) {
while (s2.size()) {
s1.push(s2.top());
s2.pop();
}
cout << s1.top() << '\n';
s1.pop();
}
else cout << "ERROR:Empty" << '\n';
}
}
}
}
7-62 windows消息队列
https://pintia.cn/problem-sets/1628020702584594432/exam/problems/1628020809572896829
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,string> PII;
int main() {
map<int,string> mp;
int n;
cin >> n;
priority_queue<PII,vector<PII>,greater<PII>> que; // 优先队列,默认为大顶堆,greater<>可以转化为小顶堆
while (n--) {
string s;
cin >> s;
if (s == "PUT") {
string s1;
int a;
cin >> s1 >> a;
que.push(make_pair(a,s1));
}
else {
if (que.size()) {
cout << que.top().second << '\n';
que.pop();
}
else cout << "EMPTY QUEUE!" << '\n';
}
}
}
7-98 出栈序列的合法性
https://pintia.cn/problem-sets/1628020702584594432/exam/problems/1628020809577091100
#include<bits/stdc++.h>
using namespace std;
int m,n,k;
bool isValid() {
int t = 1;
stack<int> sk;
bool flag = true;
for (int i = 1; i <= n; i++) {
int data;
cin >> data;
if (t < data) {
for (int j = t; j <= data; j++) {
sk.push(j);
}
t = data + 1;
if (sk.size() > m) flag = false;
}
if (data == t) {
t++;
continue;
}
if (!sk.empty() && data == sk.top()) {
sk.pop();
continue;
}
if (data < t)flag = false;
}
if (flag) return true;
else return false;
}
int main() {
cin >> m >> n >> k;
while (k--) {
if (isValid()) puts("YES");
else puts("NO");
}
}
天梯赛3 括号匹配
https://pintia.cn/problem-sets/1642514333126778880/exam/problems/1642514395693215752
#include<bits/stdc++.h>
using namespace std;
bool isValid(string s) {
stack<char> sk;
for (int i = 0; i < (int)s.size(); i++) {
if (s[i] == '(') sk.push(')');
else if (s[i] == '[') sk.push(']');
else if (s[i] == '{') sk.push('}');
else if (sk.empty()) return cout << "Extra right brackets",0;
else if (s[i] != sk.top()) return cout << "Brackets not match",0;
else if (s[i] == sk.top()) sk.pop();
}
if (sk.size()) return cout << "Extra left brackets",0;
return true;
}
int main() {
string s;
cin >> s;
if (isValid(s)) {
cout << "Brackets match" << '\n';
}
}