一、向量 vector
数组的限制
vector的使用
vector :动态数组 C++风格的容器,是顺序存储的线性表,需要#include <vector>
数组:int arr[10];
vector:vector<int> vec;//此时长度为0,需要尾部扩容
vector的初始化
访问 修改 调整 vector(重点)
随机位置的插入和删除
例题5.1 完数和盈数
一个数如果恰好等于它的各因子(该数本身除外)子和,如:6=3+2+1。则称其为“完数”;若因子之和大于该数,则称其为“盈数”。 求出2到60之间所有“完数”和“盈数”。
输入描述:
题目没有任何输入。
输出描述:
输出2到60之间所有“完数”和“盈数”,并以如下形式输出: E: e1 e2 e3 ......(ei为完数) G: g1 g2 g3 ......(gi为盈数) 其中两个数之间要有空格,行尾不加空格。
输入:
无输出:
按题目要求进行输出即可。
代码:
#include <cstdio>
#include <vector>
using namespace std;
int print(vector<int>v) {
printf("%d", v[0]);
int i;
for (i = 1; i < v.size(); i++)
printf("% d", v[i]);
return 0;
}
int main() {
vector<int>wanshu;
vector<int>yingshu;
vector<int>factor;
int x;
for (x = 1; x <= 60; x++) {
int sum = 0;
factor.clear();
for (int i = 1; i < x; i++)
if (x % i == 0)
factor.push_back(i);
for (int i = 0; i < factor.size(); i++)
sum += factor[i];
if (sum == x)wanshu.push_back(x);
else if (sum > x)yingshu.push_back(x);
}
printf("E: ");
print(wanshu);
printf("\n");
printf("G: ");
print(yingshu);
return 0;
}
vector的实现原理
vector的扩容原理
二、队列
标准库提供了队列的实现
include <queue>
using namespace std;
整型队列 queue<int>
入队 push 入队从尾部入
出队 pop 出队从队头出
判断为空 empty
返回队头元素 front
返回队尾元素 back
队列大小 size
例题5.2 约瑟夫问题No.2
n 个小孩围坐成一圈,并按顺时针编号为1,2,…,n,从编号为 p 的小孩顺时针依次报数,由1报到m ,当报到 m 时,该小孩从圈中出去,然后下一个再从1报数,当报到 m 时再出去。如此反复,直至所有的小孩都从圈中出去。请按出去的先后顺序输出小孩的编号。
输入
每行是用空格分开的三个整数,第一个是n,第二个是p,第三个是m (0 < m,n < 300)。
最后一行是:
0 0 0输出
按出圈的顺序输出编号,编号之间以逗号间隔。
样例输入
8 3 4 0 0 0样例输出
6,2,7,4,3,5,1,8
循环队列:先出队,再入队列
代码
#include <cstdio>
#include <queue>
using namespace std;
//约瑟夫问题
//从p号小孩开始报数,从1报到m,逢m的要出队,下一个接着从1开始报数,当报到m再出去
int main () {
int n, p, m;
//将p->..->n号小孩入队
while (scanf("%d%d%d", &n, &p, &m) != EOF) {
if (n == 0 && p == 0 && m == 0) {
break;
}
queue<int> children;
//将第一轮要喊编号的孩子排好队
for (int i = p, j = 0; j < n; ++j) {
//将n个小孩从编号为p的开始放入队列 : p-> p+1 ... n -> 1-> ...-> p-1
//如3->4->...->8->1->2
children.push(i);
++i;
if (i > n) {
i = 1;
}
}
//开始叫号
int num = 1;
while (true) {
int cur = children.front();
children.pop();
if (num == m) {//恰好叫到m,要区分是否是最后一个出队的学生
num = 1;
if (children.empty()) {//最后一个学生出队,则直接打印并且退出循环
printf("%d ", cur);
break;
}else {
printf("%d,", cur);
}
}else {
//还没叫到号
++num;
children.push(cur);
}
}
}
return 0;
}
例题5.3 猫狗收容所
有家动物收容所只收留猫和狗,但有特殊的收养规则,收养人有两种收养方式,
第一种为直接收养所有动物中最早进入收容所的,
第二种为选择收养的动物类型(猫或狗),并收养该种动物中最早进入收容所的。给定一个操作序列int[][2] ope(C++中为vector<vector<int>>)代表所有事件。
若第一个元素为1,则代表有动物进入收容所,第二个元素为动物的编号,正数代表狗,负数代表猫;
若第一个元素为2,则代表有人收养动物,第二个元素若为0,则采取第一种收养方式(最早进入收容所的猫/狗),若为1,则指定收养狗,若为-1则指定收养猫。
请按顺序返回收养的序列。若出现不合法的操作,即没有可以符合领养要求的动物,则将这次领养操作忽略。输入
第一个是n,它代表操作序列的次数。接下来是n行,每行有两个值m和t,分别代表题目中操作的两个元素。
输出
按顺序输出收养动物的序列,编号之间以空格间隔。
样例输入:
6
1 1
1 -1
2 0
1 2
2 -1
2 1
样例输出:
1 -1 2
代码 :
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
//例题5.3 猫狗收容所
struct Animal
{
int num; //猫/狗自身的编号
int seq; //被收留的次序
};
int main ()
{
queue<Animal> Dogque; //狗子序列
queue<Animal> Catque; //猫咪序列
int seq = 0;
int n;
scanf("%d", &n);
for (int i = 0; i < n; ++i)
{
int type;//表示操作是要入队还是出队(收留还是收养)
int num;//存放动物编号or收养方式
scanf("%d%d", &type, &num);
if (type == 1) //表示猫狗入队
{
if (num > 0)
{//处理狗
Animal dog;
dog.seq = seq;
dog.num = num;
Dogque.push(dog);
++seq;
}
else
{//处理猫
Animal cat;
cat.seq = seq;
cat.num = num;
Catque.push(cat);
++seq;
}
}
else
{ //表示猫狗出队,被收养
if (num == 0) //表示不区分猫狗的收养方式
{
//1.无猫无狗
if (Dogque.empty() && Catque.empty())
{
continue;//跳出本次循环体的剩余代码
}
//2.收养狗的情况
//2.a 无猫有狗
//2.b 有猫有狗但狗序号更小
else if (Catque.empty() ||
!Catque.empty() && !Dogque.empty() && Dogque.front().seq < Catque.front().seq)
{
printf("%d ", Dogque.front().num);
Dogque.pop();
}
else
{
printf("%d ", Catque.front().num);
Catque.pop();
}
}
else if (num == 1) //收养狗
{
if (Dogque.empty())
{
continue;
}
printf("%d ", Dogque.front().num);
Dogque.pop();
}
else
{//收养猫
if (Catque.empty())
{
continue;
}
printf("%d ", Catque.front().num);
Catque.pop();
}
}
}
printf("\n");
return 0;
}
栈
stack<typename> myStack //定义
.size()栈大小
.push()加入元素到栈当中压栈
.top()获取栈顶元素的内容
.pop()弹栈
.empty()判断栈是否为空
例题5.4 Zero-complexity Transposition
You are given a sequence of integer numbers. Zero-complexity transposition of the sequence is the reverse of this sequence. Your task is to write a program that prints zero-complexity transposition of the given sequence.
输入描述:
For each case, the first line of the input file contains one integer n-length of the sequence (0 < n ≤ 10 000). The second line contains n integers numbers-a1, a2, …, an (-1 000 000 000 000 000 ≤ ai ≤ 1 000 000 000 000 000).
输出描述:
For each case, on the first line of the output file print the sequence in the reverse order.
输入:
5 -3 4 6 -8 9输出:
9 -8 6 4 -3
整数的数据类型 |
代码
#include <iostream>
#include <cstdio>
#include <stack>
using namespace std;
int main(){
long long tmp;
int n;
stack<long long>s;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%lld",&tmp);
s.push(tmp);
}
while(!s.empty()){
printf("%d ",s.top());
s.pop();
}
return 0;
}
例题5.5 括号匹配问题
在某个字符串(长度不超过100)中有左括号、右括号和大小写字母;规定(与常见的算数式子一样)任何一个左括号都从内到外与在它右边且距离最近的右括号匹配。写一个程序,找到无法匹配的左括号和右括号,输出原来字符串,并在下一行标出不能匹配的括号。不能匹配的左括号用"$"标注,不能匹配的右括号用"?"标注.
输入
输入包括多组数据,每组数据一行,包含一个字符串,只包含左右括号和大小写字母,字符串长度不超过100
注意:cin.getline(str,100)最多只能输入99个字符!输出
对每组输出数据,输出两行,第一行包含原始输入字符,第二行由"$","?"和空格组成,"$"和"?"表示与之对应的左括号和右括号不能匹配。
样例输入
((ABCD(x) )(rttyy())sss) (
样例输出
((ABCD(x) $$ )(rttyy())sss)( ? ?$
读取字符串的操作例子: |
思路:
先假定左括号非法,加$符号,当对找到对应的右括号时再合法,转为空格
#include<stdio.h>
#include<stack>
#include<string>
using namespace std;
int main(){
char arr[200];
while(fgets(arr,200,stdin)!=NULL){
string str; //原始字符串
string res; //处理后字符串
stack<int> number; //存放(在字符串中的下标
str=arr;
str.pop_back();
for(int i=0;i<str.size();i++){
if(str[i]=='('){
res.push_back('$'); //假设左括号均非法,将(下标入栈
number.push(i);
}
else if(str[i]==')'){
if(number.empty()){
//)非法
res.push_back('?');
}
else{
//)合法,将栈顶(置为' ',并出栈
res.push_back(' ');
res[number.top()]=' ';
number.pop();
}
}
else{
res.push_back(' ');
}
}
printf("%s\n%s\n",str.c_str(),res.c_str());
}
}
例题5.5 简单计算器
读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。
输入描述:
测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。中间有空格,所以用fgets while(fgets(buf,300,stdin) != NULL)
输出描述:
对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。
输入:
1 + 2 4 + 2 * 5 - 7 / 11 0输出:
3.00 13.36
表达式解析的问题
运算符栈出栈顺序:
表达式解析的数据结构的设计
string类型 的 push_back()
push_back() 是算法语言里面的一个 函数名。 C++ 中的vector头文件里面就有这个push_back函数,在vector类中作用为在vector尾部加入一个数据。string中也有这个函数,作用是字符串之后插入一个字符。
用法例如:
string name = "HAHA";
name.push_back('Y');name的结果变为:
name= HAHAY
//stod --> string to double
#include "stdio.h"
#include "string"
#include "stack"
#include "map"
using namespace std;
stack<char> operStack;
stack<double> numStack;
string str;
void calculate(){
char operation = operStack.top();operStack.pop();
double a = numStack.top();numStack.pop();
double b = numStack.top();numStack.pop();
double num;
switch (operation) {
case '+':
num=a+b;
numStack.push(num);break;
case '-':
num=b-a;
numStack.push(num);break;
case '*':
num=a*b;
numStack.push(num);break;
case '/':
num=b/a;
numStack.push(num);break;
default:
break;
}
}
int main(){
char buf[300];
map<char,int> priority = {
{'$',0},
{'+',1},{'-',1},
{'*',2},{'/',2}
};
while (fgets(buf,300,stdin)!=NULL){
str=buf;
str.pop_back();
if(str=="0")
break;
str.push_back('$');
string num;
for (int i = 0; i < str.size(); ++i) {
if(str[i]>='0' && str[i]<='9'){ //是数字
num.push_back(str[i]);
} else if(str[i] == ' '){//为空格时
if(!num.empty()){ //若数字不为空,则压入栈中
numStack.push(stod(num));//stod --> string to double
num.clear();
}
} else{ //此为+ - * /情况
if(str[i]=='$'){
if(!num.empty()){ //若数字不为空,则压入栈中
numStack.push(stod(num));
num.clear();
}
}
while (!operStack.empty() && priority[operStack.top()] >= priority[str[i]]){//要弹栈
calculate();
}
operStack.push(str[i]);
}
}
printf("%.2lf\n",numStack.top());
numStack.pop();
str.clear();
}
}