如何使用 STL 算法找到最小值和最大值?

How to find min and max using STL algorithms?

本文关键字:最小值 最大值 何使用 STL 算法      更新时间:2023-10-16

我有resturentratings。如何使用 STL 容器查找餐厅评级的最小值和最大值?我是否需要使用最大和最小评级的 STL 算法?我将不得不使用任何方法找到平均评分。

Id  Name
1   McDonalds 
2   Wendys 
3   Burger King
Id  Resturent Rating
1     100
2     90
3     85
1     80
2     90
3     100
1     85
2     75
3     100


int main {
map<int, string> resturent;
stu.insert(pair<int, string>(1,  "McDonalds")));
stu.insert(pair<int, string>(2, "Wendys")));
stu.insert(pair<int, string>(3,"Burger King")));
multimap<int, int> rating;
testScore.insert(pair<int, int>(1, 10));
testScore.insert(pair<int, int>(2, 9));
testScore.insert(pair<int, int>(3, 8));
testScore.insert(pair<int, int>(1, 8));
testScore.insert(pair<int, int>(2, 6));
testScore.insert(pair<int, int>(3, 10));
testScore.insert(pair<int, int>(1, 5));
testScore.insert(pair<int, int>(2, 7));
testScore.insert(pair<int, int>(3, 9));
}

预期答案:

Resturent:McDonalds Id:1
Max Rating: 10
Min Rating: 5
Average Rating:7.67

您可以定义以下类,Ratings用于检索餐厅评级的统计信息:

#include <limits>
class Ratings {
unsigned num_{0};  // number of ratings inserted
long long sum_{0}; // sum of all the inserted ratings
int min_{std::numeric_limits<int>::max()};
int max_{std::numeric_limits<int>::min()};
public:
void insert_rating(int rating) {
// update minimum
if (rating < min_)
min_ = rating;
// update maximum
if (rating > max_)
max_ = rating;
// update sum
sum_ += rating;
// update number of ratings
num_++;
}
double average() const {
// calculate the average rating
return (double)sum_ / num_; 
}
int min() const { return min_; }
int max() const { return max_; }
};

它保留插入的最小值、最大值、总和和评级数量的跟踪。因此,获得最小值、最大值和平均值是在恒定时间内完成的。添加评级也是在恒定时间内完成的,因为它只需要恒定数量的操作,即更新min_max_sum_num_

然后,您需要为要评级的每家餐厅提供一个Rating对象,即restaurant地图中的每个元素。您可以使用与restaurant映射大小相同的Ratings 向量,并使用(从零开始(餐厅的 id 为向量中的元素编制索引:

int main() {
// id to restaurant
std::map<int, std::string> restaurant;
restaurant.insert({0, "McDonalds"});
restaurant.insert({1, "Wendys"});
restaurant.insert({2, "Burger King"});
// a Ratings object for each restaurant
std::vector<Ratings> ratings(restaurant.size());
ratings[0].insert_rating(10);
ratings[1].insert_rating(9);
ratings[2].insert_rating(8);
ratings[0].insert_rating(8);
ratings[1].insert_rating(6);
ratings[2].insert_rating(10);
ratings[0].insert_rating(5);
ratings[1].insert_rating(7);
ratings[2].insert_rating(9);
for (int i = 0; i < ratings.size(); ++i) {
std::cout << "Restaurant: " << restaurant[i] << ", Id: " << i << 'n';
std::cout << "Max Rating: " << ratings[i].max() << 'n';
std::cout << "Min Rating: " << ratings[i].min() << 'n';
std::cout << "Average Rating: " << ratings[i].average() << 'n';
std::cout << 'n';
}
}

该程序的输出是:

Restaurant: McDonalds, Id: 0
Max Rating: 10
Min Rating: 5
Average Rating: 7.66667
Restaurant: Wendys, Id: 1
Max Rating: 9
Min Rating: 6
Average Rating: 7.33333
Restaurant: Burger King, Id: 2
Max Rating: 10
Min Rating: 8
Average Rating: 9

我想向您展示一种可能的解决方案。有很多。。。

我的猜测是老师请求了 2 个单独的容器,因为他可能想稍后解释数据库,其中我们有一个主键"id"的父表"Student"和一个带有外键"id"(不是 NULL(的相关子表"Score"。

好的,那么让我们采用这种方法。我们创建 2 个类:"学生"和"分数"。我们构建它的载体。然后我们有一个带有属性的表(向量(。类成员是表的属性。这些表使用一些测试值进行初始化。

为了显示所有学生的所有计算值,我们使用基于for循环的范围遍历"students"表。然后,我们过滤"分数"表,以获取当前评估的学生ID。这类似于带有子查询的数据库 where 子句。

无论如何。然后我们将有一个表格,仅包含该学生的分数。然后我们对 STL 容器使用标准算法,如 std::min_element、std::max_element 和 std::accumulate。std::accumulate用于计算平均值。因此,值的总和除以值的数量。

对于算法,我们使用 lambda 来访问正确的元素。

#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <numeric>
struct Student
{
unsigned int id{};
std::string name{};
};
struct Score
{
unsigned int id{};
unsigned int score{};
};
std::vector<Student> students{ {1U,"John"},{2U,"Mary"},{3U,"Luke"},{4U,"Lisa"} };
std::vector<Score> scores{ {3U,100U},{4U,80U},{2U,90U},{1U,85U},{1U,95U},{2U,90U},{3U,80U},
{4U,95U},{3U,100U},{1U,80U},{2U,85U},{3U,95U},{1U,95U},{2U,100U},{3U,95U} };
int main()
{
// Calculating all results
for (const Student& student : students) {
// Filter out the scores for this student
std::vector<Score> scoreForThisStudent{};
std::copy_if(scores.begin(), scores.end(), std::back_inserter(scoreForThisStudent), [&student](const Score & s) { return student.id == s.id; });
// Check, if scores are available. Calculate only in this case
if (scoreForThisStudent.size()) {
std::cout << "nStudentnID: " << std::left << std::setw(4) << student.id << "    Name: " << student.name
<< "nMin Score:        " << std::min_element(scoreForThisStudent.begin(), scoreForThisStudent.end(), [](const Score & s1, const Score & s2) {return s1.score < s2.score; })->score
<< "nMax Score:        " << std::max_element(scoreForThisStudent.begin(), scoreForThisStudent.end(), [](const Score & s1, const Score & s2) {return s1.score < s2.score; })->score
<< "nNumber of Scores: " << scoreForThisStudent.size()
<< "nAverage:          " << std::accumulate(scoreForThisStudent.begin(), scoreForThisStudent.end(), 0U, [](const unsigned int s1, const Score & s2) {return s1 + s2.score; }) / scoreForThisStudent.size() << "n";
}
}
return 0;
}

由于编写 lambda 的工作有些乏味,我们做了一个小的改进,并重载了 Score 类的"<"和"+"运算符。这样就不需要lambda,std::algorithms将直接使用类中的运算符。

请看:

#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <numeric>
struct Student
{
unsigned int id{};
std::string name{};
};
struct Score
{
unsigned int id{};
unsigned int score{};
bool operator < (const Score& other) const { return score < other.score; }
friend unsigned int operator + (const unsigned int val, const Score& other) { return val + other.score; }
};
std::vector<Student> students{ {1U,"John"},{2U,"Mary"},{3U,"Luke"},{4U,"Lisa"} };
std::vector<Score> scores{ {3U,100U},{4U,80U},{2U,90U},{1U,85U},{1U,95U},{2U,90U},{3U,80U},
{4U,95U},{3U,100U},{1U,80U},{2U,85U},{3U,95U},{1U,95U},{2U,100U},{3U,95U} };
int main()
{
// Calculating all results
for (const Student& student : students) {
// Filter out the scores for this student
std::vector<Score> scoreForThisStudent{};
std::copy_if(scores.begin(), scores.end(), std::back_inserter(scoreForThisStudent), [&student](const Score &s) { return student.id == s.id; });
// Check, if scores are available. Calculate only in this case
if (scoreForThisStudent.size()) {
// Calculate all required values
std::cout << "nStudentnID: " << std::left << std::setw(4) << student.id << "    Name: " << student.name
<< "nMin Score:        " << std::min_element(scoreForThisStudent.begin(), scoreForThisStudent.end())->score
<< "nMax Score:        " << std::max_element(scoreForThisStudent.begin(), scoreForThisStudent.end())->score
<< "nNumber of Scores: " << scoreForThisStudent.size() 
<< "nAverage:          " << std::accumulate(scoreForThisStudent.begin(), scoreForThisStudent.end(), 0U) / scoreForThisStudent.size() << "n";
}
}
return 0;
}

希望这有助于更好地理解

您可以分别使用 min_element(start_iterator, end_iterator( 和 max_element(start_iterator, end_iterator(,将迭代器返回到范围内的最大值。给你!!!

#include <iostream>     
#include <algorithm>    
using namespace std;
int main () {
int myints[] = {3,7,2,5,6,4,9};
//Method 1
int minElement = *min_element(myints, myints+7);
int maxElement = *max_element(myints, myints+7);      
cout<<"Max: "<< maxElement <<"n";
cout<<"Min: "<< minElement <<"n";

// Method 2: added by @HolyBlackCat
int result = minmax_element(myints, myints+7);   //return a pair with iterator pointing to minimum element
cout<<"Max: "<< *result.first <<"n";
cout<<"Min: "<< *result.second <<"n";

// Method 3:
int result = minmax(myints, myints+7);   //return a pair of min,max element
cout<<"Max: "<< result.first <<"n";
cout<<"Min: "<< result.second <<"n";

return 0;
}

PS:不包括last_iterator所指的元素,即它在上限上是排他性的。