简体   繁体   English

在列表(C ++ STL)中找到最常见的元素?

[英]Finding most common element in a list (C++ STL)?

I have a program where I have to find the most common element in a list of integers. 我有一个程序,必须在整数列表中找到最常见的元素。 I do this with the program below, but the problem is, I suspect that the erase function messes up with the iterator incrementation in the countRepetition() function. 我使用下面的程序执行此操作,但是问题是,我怀疑擦除功能与countRepetition()函数中的迭代器增量countRepetition() My question is how can I fix the problem or if this is not the issue what is it? 我的问题是我该如何解决问题,或者如果这不是问题,那是什么?

Thanks in advance. 提前致谢。

You have a couple issues. 你有几个问题。 First, as you suspected, was the incorrect use of erase . 首先,正如您所怀疑的那样,错误地使用了erase When you erase an iterator it invalidates the iterator. 当您删除迭代器时,它将使迭代器无效。 Any use of the iterator afterwards is undefined behavior. 此后对迭代器的任何使用都是未定义的行为。 Since erase returns the next valid iterator what you can do is restructure the loop like 由于erase返回下一个有效的迭代器,因此您可以执行以下操作:

for (START = l.begin(); START != l.end();) { // do not increment here
    if (*START) {
        counter++;
        START = l.erase(START); // erase and get next
    }
    else
    {
        ++START; // go to next
    }
}

So now at least you loop through the list. 所以现在至少您可以遍历列表。 Unfortunately you will still have an invalid iterator in main . 不幸的是, main仍然会有一个无效的迭代器。 You pass START from main to countRepetition and when that iterator is erased from the list you then have an invalid iterator. 您传递STARTmaincountRepetition和当迭代器从列表中删除你再有一个无效的迭代器。 What you need to do is get a new begin iterator from the list each iteration since you are always erasing the first element. 您需要做的是每次迭代都从列表中获得一个新的begin迭代器,因为您始终会擦除第一个元素。 That would make your for loop look like 那会让你的for循环看起来像

for (START = l.begin(); START != l.end(); START = l.begin()) {
    m.push_back(countRepetition(START));
}

Another issue is you just check if the character is not 0 . 另一个问题是,您只需检查字符是否不为0 If you are counting repetitions you need to make sure you are checking that the iterator is the same character. 如果要计算重复次数,则需要确保检查迭代器是否为相同字符。 I'll leave that for you to implement. 我将其留给您实施。


I would also like to point out there is an easier way to do all of this. 我还想指出,有一种更简单的方法可以完成所有这些工作。 A std::map lets you build a histogram very easily. 使用std::map可以非常轻松地构建直方图。 Combine that with std::max_element and you could write your entire program as 将其与std::max_element结合使用,您可以将整个程序编写为

int main()
{
    std::map<char, int> histogram;
    while ('0' != (number = getchar()))
        ++histogram[number]; // add to map, increment count of occurances

    auto most_frequent = *std::max_element(histogram.begin(), 
                                           histogram.end(), 
                                           [](const auto& lhs, const auto& rhs) { return lhs.second < rhs.second; }).first;
    std::cout << most_frequent;    
    return 0;
}

This is probably what you are looking for: 这可能是您要寻找的:

#include <iostream>
#include <list>
#include <vector>
#include <map>

using namespace std;

list <char> l;
map<char, int> ans;
int main()
{
    char c;
   do{
       c = getchar();
       l.push_back(c);
   }while(c != '0');
   for(auto chr: l){
       ans[chr]++;
   }
   char ch;
   int mx = 0;
   for(auto k: ans){
       if(k.second > mx)
       {
           ch = k.first;
           mx = k.second;
       }
   }
   cout<<ch<<" : "<<mx;
}

Your problem is that you use global variables everywhere. 您的问题是您到处都使用全局变量。 The global START is changed in two loops, so you only access the first loop once, then it is changed again in the second function and you don't execute the first loop a second time. 全局START在两个循环中进行了更改,因此您只能访问第一个循环一次,然后在第二个函数中再次对其进行更改,而无需再次执行第一个循环。

Why do you use the global variables? 为什么要使用全局变量? You should not use them but use local variables. 您不应使用它们,而应使用局部变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM