《算法笔记》6.5小节 6.6小节 6.8小节 6.9小节——C++标准模板库(STL)介绍->pair algorithm

6.5 queue队列
在这里插入图片描述

问题 A: C语言-数字交换
问题描述:输入10个整数,将其中最小的数与第一个数对换,把最大的数与最后一个数对换。写三个函数; ①输入10个数;②进行处理;③输出10个数。

  • 输入
10个整数
  • 输出
整理后的十个数,每个数后跟一个空格(注意最后一个数后也有空格)
  • 样例输入
2 1 3 4 5 6 7 8 10 9
  • 样例输出
1 2 3 4 5 6 7 8 9 10 

这题用数组就可以解决哇,不知道为啥按在这

#define _CRT_SECURE_NO_WARNINGS 1
#include <cstdio>
#include <string>
#include <iostream>
#include <map>
#include<queue>
using namespace std;
int main()
{
	int a[10];
	int i, max, min;
	int temp;
	
	max = min = 0;//先让最大和最小的元素下标为0
	for (i = 0; i < 10; i++)
	{
		scanf("%d",&a[i]);
		if (a[i] > a[max])
			max = i;
		if (a[i] < a[min])
			min = i;
	}
	//输入完毕,max和min保留了最大和最小元素的下标
	temp = a[max];
	a[max] = a[9];
	a[9] = temp;
	temp = a[min];
	a[min] = a[0];
	a[0] = temp;
	for (i = 0; i < 10; i++)
	{
		printf("%d ",a[i]);
	}
	return 0;
}

6.6 priority_queue队列
在这里插入图片描述

⭐⭐⭐⭐问题 A: 任务调度
问题描述:读入任务调度序列,输出n个任务适合的一种调度方式。

  • 输入
输入包含多组测试数据。
每组第一行输入一个整数n(n<100000),表示有n个任务。
接下来n行,每行第一个表示前序任务,括号中的任务为若干个后序任务,表示只有在前序任务完成的情况下,后序任务才能开始。若后序为NULL则表示无后继任务。
  • 输出
输出调度方式,输出如果有多种适合的调度方式,请输出字典序最小的一种。
  • 样例输入
4
Task0(Task1,Task2)
Task1(Task3)
Task2(NULL)
Task3(NULL)
  • 样例输出
Task0 Task1 Task2 Task3

这道题真是把之前的stl用了个遍,绝绝子

#define _CRT_SECURE_NO_WARNINGS 1
#include <cstdio>
#include <iostream>
#include <unordered_map>
#include <queue>
#include <string>
using namespace std;
struct Task
{
    string name;//名字
    int level;//顺序
    friend bool operator <(const Task& t1, const Task& t2)
    {
        if (t1.level != t2.level)
            return t1.level > t2.level;
        else
            return t1.name > t2.name;//按照优先级小的排序如果优先级相同就按照字典序小的排序
    }
};
//临时字符串str,队列task和无序映射list
void dispose(string str, priority_queue<Task>& task, unordered_map<string, int>& list)
{
    string first;
    int pos;
    int firstlevel;
    pos = str.find('(');
    first = str.substr(0, pos);//first是前序任务
    str.erase(0, pos + 1);
    if (list.count(first) == 0)//如果List里面没有这个任务的映射
    {
        //新建task,并且task的优先级为0
        Task newtask;
        newtask.name = first;
        newtask.level = 0;
        //将这个新建的task推入task队列
        task.push(newtask);
        //记录firstlevel=0;first的映射为0
        firstlevel = list[first] = 0;
    }
    else
    {
        //如果有这个映射,说明task队列中已经有了这个任务,直接记录first的映射
        firstlevel = list[first];
    }
    while (str.empty() == false)//当str字符串不为空时
    {
        string last;
        pos = str.find(',');
        if (pos == string::npos)//如果没有找到,
        {
            pos = str.find(')');
            last = str.substr(0, pos);//直接找括号里唯一的后序任务
            str.clear();
        }
        else
        {
            last = str.substr(0, pos);//否则记录第一个后续任务
            str.erase(0, pos + 1);
        }
        if (last != "NULL")
        {
            //还有任务的时候
            Task newtask;
            newtask.name = last;
                //后续任务是前序任务的Level+1
            newtask.level = firstlevel + 1;
            list[last] = newtask.level;
            task.push(newtask);
        }
    }
}
int main()
{
    int n;
    while (~scanf("%d", &n))
    {
        priority_queue<Task> task;//队列task
        unordered_map<string, int> list;//task name 到优先级Level的映射
        string temp;//临时字符串temp;
        //下面输入字符串并排序
        for (int i = 0; i < n; i++)
        {
            cin >> temp;
            dispose(temp, task, list);
        }
        //当队列不为空时,不断输出队首任务
        while (task.empty() == false)
        {
            cout << task.top().name;
            task.pop();
            if (!task.empty())
            {
                cout << " ";
            }
            //每两个任务之间输出空格
        }
        list.clear();
    }
    return 0;
}

6.7 stack栈
栈的函数和优先队列基本一致,用途:可以用栈来模拟递归算法(用的也比较少)
⭐⭐⭐⭐问题 A: 简单计算器
问题描述:读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。

  • 输入
测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。
  • 输出
对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。
  • 样例输入
30 / 90 - 26 + 97 - 5 - 6 - 13 / 88 * 6 + 51 / 29 + 79 * 87 + 57 * 92
0
  • 样例输出
12178.21

中缀表达式转换为后缀表达式,然后处理数字栈和符号栈

#define _CRT_SECURE_NO_WARNINGS 1
#include <cstdio>
#include <iostream>
#include <string>
#include <unordered_map>
#include <stack>
#include <sstream>
using namespace std;
//将字符变成数字
int str_to_int(const string& string_temp)
{
    int temp;
    stringstream stream(string_temp);
    stream >> temp;
    return temp;
}

void compute(stack<double>& number, stack<string>& sign)
{
    double b = number.top();
    number.pop();
    double a = number.top();
    number.pop();
    string op = sign.top();
    sign.pop();
    if (op == "+")
    {
        number.push(a + b);
    }
    else if (op == "-")
    {
        number.push(a - b);
    }
    else if (op == "*")
    {
        number.push(a * b);
    }
    else
    {
        number.push(a / b);
    }
}
double dispose(unordered_map<string, int> isp, unordered_map<string, int> osp, string str)
{
    stack<double> number;
    stack<string> sign;
    int flag = 0;
    while (str.empty() == false)//当str不为空时
    {
        string temp;//临时变量temp
        int pos = str.find(" ");
        //获得第一个数字
        if (pos != string::npos)
        {
            temp += str.substr(0, pos);
            str.erase(0, pos + 1);
        }
        //获得最后一个数字
        else
        {
            temp = str;
            str.clear();
        }
        if (flag == 0)//入栈数字
        {
            number.push(str_to_int(temp));//将数字入number栈
            flag = 1;
        }
        else//入栈符号
        {
            if (sign.empty() == false)//sign字符串不为空时
            {
                if (isp[sign.top()] >= osp[temp])//先乘除后加减
                {
                    while (sign.empty() == false)//sign字符串不为空时
                    {
                        if (isp[sign.top()] < osp[temp])
                            break;
                        compute(number, sign);
                    }
                }
            }
            sign.push(temp);//符号入sign栈
            flag = 0;
        }
    }
    while (sign.empty() == false)
    {
        compute(number, sign);
    }
    return number.top();
}

int main()
{
    char a[210];//每行不超过200字符
    string temp;
    while (gets_s(a))
    {
        //将表达式存到string中
        for (int i = 0; i < 200; i++)
        {
            if (a[i] != '\0')
            {
                temp += a[i];
            }
            else
            {
                break;
            }
        }
        if (temp != "0")
        {
            unordered_map<string, int> isp, osp;//定义映射isp和osp
            isp["+"] = 1;
            isp["-"] = 1;
            isp["*"] = 2;
            isp["/"] = 2;
            osp["+"] = 1;
            osp["-"] = 1;
            osp["*"] = 2;
            osp["/"] = 2;
            double result = dispose(isp, osp, temp);

            printf("%.2f\n", result);
            temp.clear();
        }
        else
        {
            break;
        }
    }
    return 0;
}

⭐⭐⭐⭐问题 B: Problem E
待解决

6.8 pair常见用法
1、用来代替二元结构体及其构造函数
2、作为map的键值来进行插入
问题 A: 重心在哪里
问题描述:每个人都知道牛顿发现万有引力的故事。自从牛顿发现万有引力后,人们用万有引力理论解决了非常多的问题。不仅如此,我们也知道了每个物体都有自己的重心。
现在,给你三角形三个顶点的坐标,你能计算出三角形的重心吗?

  • 输入
题目包含多组测试数据。第一行输入一个正整数n,表示测试数据的个数,当n=0时,输入结束。
接下来n行,每行包含6个数字x1,y1,x2,y2,x3,y3,表示三角形三个顶点的坐标。
  • 输出
对于每组输入,输出重心的坐标,结果保留1位小数。
  • 样例输入
2
1.0 2.0 3.0 4.0 5.0 2.0
1.0 1.0 4.0 1.0 1.0 5.0
0
  • 样例输出
3.0 2.7
2.0 2.3
#define _CRT_SECURE_NO_WARNINGS 1
#include <cstdio>
#include <iostream>
#include <string>
#include <unordered_map>
#include <stack>
#include<map>
#include <sstream>
using namespace std;
int main()
{    
    pair<double, double> p[4];
    int n, i,j;
    while (scanf("%d", &n) != EOF)
    {
        if (n == 0)
            break;
        for (i = 0; i < n; i++)
        {
            for (j = 0; j < 3; j++)         
                scanf("%lf %lf", &p[j].first, &p[j].second);//输入                
                    
            p[3].first = (p[0].first + p[2].first + p[1].first) * 1.0 / 3;
            p[3].second = (p[0].second + p[2].second + p[1].second) * 1.0 / 3;
            printf("%.1f %.1f\n", p[3].first, p[3].second);
        }
    }    
    return 0;
}

6.9 algorithm
问题AC都是基础题,代码不贴了
问题 B: 全排列
问题描述:给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。
我们假设对于小写字母有’a’ < ‘b’ < … < ‘y’ < ‘z’,而且给定的字符串中的字母已经按照从小到大的顺序排列。

  • 输入
输入只有一行,是一个由不同的小写字母组成的字符串,已知字符串的长度在16之间。
  • 输出
输出这个字符串的所有排列方式,每行一个排列。要求字母序比较小的排列在前面。字母序如下定义:
已知S = s1s2...sk , T = t1t2...tk,则S < T 等价于,存在p (1 <= p <= k),使得
s1 = t1, s2 = t2, ..., sp - 1 = tp - 1, sp < tp成立。

注意每组样例输出结束后接一个空行。
  • 样例输入
xyz
  • 样例输出
xyz
xzy
yxz
yzx
zxy
zyx

这题注意使用next_permutation就可以啦

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int main()
{    
    char a[1100];
    int len;
    while (scanf("%s", a)!=EOF)
    {        
        len = strlen(a);
        do {
            printf("%s\n",a);
        } while (next_permutation(a, a+len));
        printf("\n");
    }
    
    return 0;
}

第六章终于结束了,真是艰难的一章啊~后仰

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值