栈与队列
1.栈的特性
需要两个指针,base指向栈底,top指向栈顶。
2.顺序栈的动态分配
3.顺序栈的静态分配
4.栈(stack)的基本操作(STL)
5.队列的特性
6.顺序队列的动态分配
7.顺序队列的静态分配
8.循环队列的队满
9.循环队列的入队
10.循环队列的出队
11.循环队列的队列长度
12.队列(queue)的基本操作(STL)
13.双端队列(deque)的基本操作(STL)
双端队列同时具有队列和栈的特性,如若从队头入队出队,则类似于队列,如若从队尾入队出队,则类似于队尾。
练习
01 栈
题目:https://www.luogu.com.cn/problem/P1739
题解:根据题意,只有左右小括号,可以将左括号入栈,遇到右括号时,弹出栈顶的左括号。如果表达式处理完毕后,栈中还有元素即不为空,说明左括号多了则输出NO,如果为空的话说明括号全部匹配则输出YES。若先遇到了右括号,则直接输出NO,不用管后面的表达式了。
#include <stack>
#include <iostream>
using namespace std;
int main(void)
{
char input_string;
stack<char> str; //声明char类型的栈
while(cin >> input_string && input_string!='@')
{
if (input_string == '(')
{
str.push(input_string);
}
if (input_string == ')')
{
if (str.empty())
{
cout << "NO" << endl;
return 0; //如果第一个遇到 )则直接输出NO且结束
}
else {
str.pop();
}
}
}
if (str.empty())
{
cout << "YES" << endl;
}
else {
cout << "NO" << endl;
}
}
02 栈
题目:https://www.luogu.com.cn/problem/UVA442
题解:
首先将矩阵及行列值存储在数组中,然后读入一行矩阵表达式(表达式是合法的,不用担心括号匹配等合法性),遇到矩阵名称入栈,遇到右括号则出栈两个矩阵m2,m1,如果m1的列不等于m2的行,则矩阵不可乘,否则计算乘法次数,并将两个矩阵相乘后的结果矩阵入栈。
#include <iostream>
#include <stack>
using namespace std;
//因为要存取矩阵的名称char类型和矩阵的大小int类型,在Python中用字典存储,在C++中用结构体存储
//定义结构体时,关于矩阵的名称是A,B,C这些,可以减去'A'后转化成整数,其值表示26个结构体中的索引
struct Matrix {
//char name; //矩阵名称
int row; //行
int col; //列
//这里使用构造函数,方便整体赋值
//若不加下面这段构造函数:赋值需要单独赋值 max_matrix[1].row=5,max_matrix[1].col=3
//加了构造函数之后,可以整体赋值 Matrix(5,3)
Matrix(int row=0,int col=0):row(row),col(col){
}
};
int main(void)
{
int num_matrix; //输入矩阵的个数
cin >> num_matrix;
Matrix max_matrix[26]; //定义最大的矩阵个数
char matrix_name;
//对于矩阵名字符串的处理
for (int i = 0; i < num_matrix; i++)
{
cin >> matrix_name;
int matrix_index = matrix_name - 'A'; //转换成整数
cin >> max_matrix[matrix_index].row >> max_matrix[matrix_index].col; //输入矩阵的行和列
}
string str;
stack<Matrix> s;
while (cin >> str)
{
int num_mul = 0;//乘法次数
bool flag = false;
for (int i = 0; i < str.size(); i++)
{
//或者使用 if (isalpha(str[i])) // isalpha():判断是否是字母
if (str[i] >= 65 && str[i] <= 90) // 如果输入的矩阵名在A到Z之间,则入栈s
{
s.push(max_matrix[str[i] - 'A']);
}
else if (str[i] == ')')
{
Matrix m2 = s.top();
s.pop();
Matrix m1 = s.top();
s.pop();
if (m1.col != m2.row) //判断m1的列是否和m2的行相等
{
flag = true;
break;
}
num_mul += m1.row * m1.col * m2.col;
//如果结构体Matrix中没写构造函数的话,需要如下:
/*Matrix tmp;
tmp.row = m1.row;
tmp.col = m2.col;
s.push(tmp);*/
s.push(Matrix(m1.row, m2.col));
}
}
if (flag)
cout << "error" << endl;
else
cout << num_mul << endl;
}
return 0;
}
03 队列
题目:https://www.luogu.com.cn/problem/UVA12100
题解:
本题中输入是:T组数据,每组数据中输入数据的个数、关心的任务在队列中的位置。(这里输入的数据是打印任务的优先级,范围是1~9)
每次都是从数据的头部取出一个任务J,若J的优先级不低于整组数据中的最高优先级,则直接打印任务J,即J从该组数据中删除,否则若小于整组数据中的最高优先级,则放到整组数据的尾部。(头部出,尾部进,满足队列的特性)
这里取出任务J后,要如何知道整组数据中的最高优先级?如果每取一个任务,都与剩下的任务进行比较,则时间复杂度为O(n²),显然不合理;若一开始就把整组数据进行降序排好,则以后每次比较时,先取降序数据中的第一个元素,若没这个大,则J出队列pop(),再push()到队尾,若不低于这个,则直接打印任务J,降序后的数据组中索引往后移一位。
为了数据降序的方便,使用STL中的vector,如下
sort(b.begin(), b.end(), greater<int>()); //将数据中的打印任务按优先级降序
3 //输入3组数据
1 0 //有1个数据,关注的任务位置是0
5 //第1组数据:5
4 2 //有4个数据,关注的任务位置是2
1 2 3 4 //第2组数据:1 2 3 4
6 0 //有6个数据,关注的任务位置是0
1 1 9 1 1 1 //第2组数据:1 1 9 1 1 1
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int main(void)
{
int T_class_data; //定义数据的组数
cin >> T_class_data;
for (int i = 0; i < T_class_data; i++)
{
int num_data, care_index_data; //定义每组数据中的数据个数、关注的任务在队列中的位置
cin >> num_data >> care_index_data;
vector<int> a_orig_data; //存储每个任务的优先级,即输入的数据
vector<int> b_sorted_data; //按优先级降序后的数据
queue<int> q_orig_index_data; //队列用以存储每个打印任务的索引
for (int i = 0; i < num_data; i++)
{
int data;
cin >> data;
a_orig_data.push_back(data);
b_sorted_data.push_back(data);
q_orig_index_data.push(i);
}
//将每组数据中的元素优先级进行降序。从该容器中第一个元素开始,是优先级最高的,每打印一次,往后加一个,则保证是最大的
sort(b_sorted_data.begin(), b_sorted_data.end(), greater<int>()); //将数据中的打印任务按优先级降序
int max_index = 0; //在已降序后的b_sorted_data中的索引
int print_order = 0;
while (!q_orig_index_data.empty())
{
int temp = q_orig_index_data.front();
if (a_orig_data[temp] < b_sorted_data[max_index])
{
q_orig_index_data.pop(); //弹出队首
q_orig_index_data.push(temp); //从队尾入队
}
else
{
//如果队首下标刚好等于关注的任务下标,则直接打印 ++k,因为k是索引从0开始,而输出的第几个打印的从1开始
if (temp == care_index_data)
{
cout << ++print_order << endl;
break;
}
else
{
q_orig_index_data.pop();
print_order++;
max_index++;
}
}
}
}
}