栈
栈无法随机访问。
1 函数实现栈
#include <iostream>
using namespace std;
int s[1000];
int t;
void Push(int x){
s[++t]=x;
}
void Pop(){
t--;
}
void Print()
{
for (int i=0; i<=t; i++){
cout<<s[i]<<" ";
}
cout<<endl;
}
void Top(){
cout<<"top = "<<s[t]<<endl;
}
int main(){
Push(1);
Push(3);
Push(5);
Push(7);
Print();
Top();
Pop();
Top();
}
运行结果:
2 宏定义实现栈
#include <iostream>
using namespace std;
int s[1000];
int t=0;
#define push(x) s[++t]=x
#define pop() t--
#define size() t
#define top() cout<<"top = "<<s[t]<<endl;
void print(){
for(int i=0; i<=t; i++){
cout<<s[i]<<" ";
}
cout<<endl;
}
int main(){
push(1);
push(3);
push(5);
push(7);
print();
top();
pop();
top();
}
运行结果:
3 STL实现栈
#include <iostream>
#include <stack>
using namespace std;
int main(){
stack<int>s;
for(int i=0; i<5; i++){
s.push(i);
}
cout<<"top = "<<s.top()<<endl;
cout<<"size = "<<s.size()<<endl;
while(!s.empty()){
cout<<"top = "<<s.top()<<endl;
s.pop();
}
return 0;
}
运行结果:
4 示例
4.1 括号序列
//给定一个字符串,里边可能包含“()”和其他字符,请编写程序检查该字符串中的括号是否成对出现。
#include <iostream>
#include <stack>
using namespace std;
bool isValid(string str)
{
stack<char> s;
char c;
int len = str.length();
for (int i = 0; i < len; i++)
{
if (str[i] == '(' || str[i] == '[' || str[i] == '{')
{
s.push(str[i]);
}
else if (str[i] == ')')
{
if (s.empty()){
return false;
}
else if ((c = s.top())&&(c == '('))
s.pop();
else{
return false;
}
}
else if (str[i] == ']')
{
if (s.empty()){
return false;
}
else if ((c = s.top())&&(c == '['))
s.pop();
else{
return false;
}
}
else if (str[i] == '}')
{
if (s.empty()){
return false;
}
else if ((c = s.top())&&(c == '{'))
s.pop();
else{
return false;
}
}
}
if (s.empty())
return true;
else
return false;
}
int main()
{
string str = "y={x+[x(x+2)]}";
bool check=true;
check = isValid(str);
if (check == true)
cout << "Valid."<<endl;
else
cout << "Not valid."<<endl;
return 0;
}
4.2 后缀表达式
题目描述
所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优先级)。
如:
3*(5-2)+7
\texttt{3*(5-2)+7}
3*(5-2)+7 对应的后缀表达式为:
3.5.2.-*7.+@
\texttt{3.5.2.-*7.+@}
3.5.2.-*7.+@。在该式中,@
为表达式的结束符号。.
为操作数的结束符号。
输入格式
输入一行一个字符串 s s s,表示后缀表达式。
输出格式
输出一个整数,表示表达式的值。
样例
样例输入
3.5.2.-*7.+@
样例输出
16
代码
// 后缀表达式(逆波兰表达式)
#include <iostream>
#include <string>
#include <stack>
using namespace std;
int caculate(string ¬ation)
{
// 1 创建一个栈对象oprands存储操作数
stack<int> oprands;
int result = 0;
// 2 从左往右遍历表达式,如果为操作数就入栈,如果是运算符,就从栈中弹出两个操作数进行计算,并将计算结果压入栈中
for (int i = 0; i < notation.length(); i++)
{
char current = notation[i];
int o1, o2;
switch (current)
{
case '+':
o1 = oprands.top();
oprands.pop(); // pop不返回任何值,无法直接进行o1=oprands.pop()操作
o2 = oprands.top();
oprands.pop();
result = o2 + o1;
oprands.push(result);
break;
case '-':
o1 = oprands.top();
oprands.pop(); // pop不返回任何值,无法直接进行o1=oprands.pop()操作
o2 = oprands.top();
oprands.pop();
result = o2 - o1; // o1-o2的后缀表达式为o1 o2 -,出栈顺序为o2 o1,除法同理
oprands.push(result);
break;
case '*':
o1 = oprands.top();
oprands.pop(); // pop不返回任何值,无法直接进行o1=oprands.pop()操作
o2 = oprands.top();
oprands.pop();
result = o2 * o1;
oprands.push(result);
break;
case '/':
o1 = oprands.top();
oprands.pop(); // pop不返回任何值,无法直接进行o1=oprands.pop()操作
o2 = oprands.top();
oprands.pop();
result = o2 / o1;
oprands.push(result);
break;
default:
int c = current - '0'; //将char current转为int c
oprands.push(c); //用c而不是current入栈
// oprands.push(current); //此处是'3'而不是数字3,入栈的是'3'的ACSII码51,后续计算都是按照51进行的,故计算错误!!
break;
}
}
result = oprands.top();
return result;
}
int main()
{
string test = "352-*7+";
cout << "test = 352-*7+ = " << caculate(test) << endl;
getchar();
return 0;
}
*注: 字符型char
与整型int
的转换
char c = '6';
int num = c - '0'; //num=6
int num = 5;
char c = num + '0'; //c='6'
字符串型转整型:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
string str = "123456";
int n = stoi(str); //转换为整型 n = 123456(转换失败时发生异常)
cout << n << endl;
// int n = atoi(str); //作用同stoi(),区别在于转换失败时返回0
getchar();
return 0;
}
队列
1 宏定义实现
#include <iostream>
#define push(x) d[++end]=x
#define pop() fnt++
#define front() s[fnt]
#define size() end-fnt+1
2 STL实现
queue是STL中的队列模板。
#include <iostream>
#include <queue>
using namespace std;
int main()
{
queue<int>q;
for(int i=0; i<5; i++){
q.push(i);
}
q.pop(); //删除队头
cout<<q.front()<<endl; //返回队头
cout<<q.back()<<endl; //返回队尾
getchar();
return 0;
}
3 示例:约瑟夫问题
题目描述
n个人(n<=100)围成一圈,从第一个人开始报数,数到m的人出列,再由下一个人重新从1开始报数,数到m的人再出圈,……依次类推,直到所有的人都出圈,请输出依次出圈人的编号.
输入格式
n m
输出格式
出圈的编号
输入输出样例
输入
10 3
输出
3 6 9 2 7 1 8 5 10 4
代码求解
//约瑟夫问题
#include <iostream>
#include <queue>
using namespace std;
void solve(){
queue<int>q;
int n,m;
cin>>n>>m;
for(int i=1; i<=n; i++){
q.push(i);
}
int curr=1;
while(!q.empty()){
if(curr==m){
cout<<q.front()<<" ";
q.pop();
curr=1;
}
else{
q.push(q.front()); //环
q.pop();
curr++;
}
}
cout<<endl;
}
int main(){
solve();
getchar();
return 0;
}
4 双端队列
STL实现
deque是STL中双端队列模板。
#include <iostream>
#include <deque>
using namespace std;
int main(){
deque<int>d;
d.push_front(1);
d.push_front(2);
d.push_back(10);
d.push_back(20);
cout<<d.front()<<endl;
cout<<d.back()<<endl;
cout<<d[2]<<endl; //支持随机访问,但是时间复杂度较高O(n)
d.pop_front();
cout<<d.front()<<endl;
getchar();
return 0;
}
5 优先队列priority_queue
优先队列是一种特殊的队列,特性在于自动排序。
和队列不一样的是,优先队列没有front()
和back()
函数,只有top()
函数,可以访问队首元素(堆顶元素),也就是优先级最高的元素。
#include <iostream>
#include <queue>
using namespace std;
int main(){
priority_queue<int>pq;
pq.push(6),pq.push(23),pq.push(2),pq.push(12),pq.push(9);
while(!pq.empty()){
cout<<pq.top()<<" ";
pq.pop();
}
cout<<endl;
getchar();
return 0;
}
//输出23 12 9 6 2
结构体,重载小于
#include <iostream>
#include <queue>
using namespace std;
struct node
{
int x, y;
bool operator<(const node &a) const
{
return y < a.y; //按照y的大小从大到小排序
}
} k;
int main()
{
priority_queue<node> q;
k.x = 10, k.y = 100;
q.push(k);
k.x = 12, k.y = 60;
q.push(k);
k.x = 14, k.y = 40;
q.push(k);
k.x = 6, k.y = 80;
q.push(k);
k.x = 8, k.y = 20;
q.push(k);
while (!q.empty())
{
node m = q.top();
q.pop();
cout << "(" << m.x << ", " << m.y << ") ";
}
cout << endl;
getchar();
return 0;
}
//输出结果:(10, 100) (6, 80) (12, 60) (14, 40) (8, 20)
less和greater优先队列
#include <iostream>
#include <queue>
using namespace std;
int main()
{
int a[7] = {6, 9, 2, 8, 1, 14, 5};
priority_queue<int, vector<int>, less<int>> p_less; //从大到小
priority_queue<int, vector<int>, greater<int>> p_greater; //从小到大
for (int i = 0; i < 7; i++)
{
p_less.push(a[i]);
p_greater.push(a[i]);
}
cout << "less<int>: " << endl;
while (!p_less.empty())
{
cout << p_less.top() << " ";
p_less.pop();
}
cout << endl;
cout << "greater<int>: " << endl;
while (!p_greater.empty())
{
cout << p_greater.top() << " ";
p_greater.pop();
}
cout << endl;
getchar();
return 0;
}
运行结果: