王道考研复试机试视频笔记 2023版新版--第五章 向量、队列和栈

一、向量 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的扩容原理

时间复杂度仍为O(N)

二、队列

标准库提供了队列的实现

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)(
?            ?$

读取字符串的操作

读一行再删除最后一个空格符

例子:

while(fgets(buf,300,stdin) != NULL)

思路:

先假定左括号非法,加$符号,当对找到对应的右括号时再合法,转为空格 

#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();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值