计算向量中的出现次数

时间:2009-07-30 03:26:59

标签: c++

这个程序从txt文件中读取数字字符串,将它们转换为整数,将它们存储在一个向量中,然后尝试以有组织的方式输出它们....

如果txt文件说:

7 5 5 7 3 117 5

程序输出:

3
5   3
7   2
117

所以,如果数字出现不止一次,它会输出发生的次数。这是迄今为止的代码。

#include "std_lib_facilities.h"

int str_to_int(string& s)
{
    stringstream ss(s);
    int num;
    ss >> num;
    return num;
}

int main()
{
    cout << "Enter file name.\n";
    string file;
    cin >> file;
    ifstream f(file.c_str(), ios::in);

    string num;
    vector<int> numbers;
    while(f>>num)
    {
        int number = str_to_int(num);
        numbers.push_back(number);
    }

    sort(numbers.begin(), numbers.end());

    for(int i = 0; i < numbers.size(); ++i)
    {
     if(i = 0 && numbers[i]!= numbers[i+1]) cout << numbers[i] << endl;
     if(i!=0 && numbers[i]!= numbers[i-1])
     {
          cout << numbers[i] << '\t' << counter << endl;
          counter = 0;
     }
     else ++counter;
    }
 }

编辑:程序陷入困境。现在正在寻找无限循环。

6 个答案:

答案 0 :(得分:8)

您可以使用数字地图来计数:

typedef map<int,unsigned int> CounterMap;
CounterMap counts;
for (int i = 0; i < numbers.size(); ++i)
{
   CounterMap::iterator it(counts.find(numbers[i]));
   if (it != counts.end()){
      it->second++;
   } else {
      counts[numbers[i]] = 1;
   }
}

...然后遍历地图以打印结果。

编辑: 正如lazypython所建议的那样:如果你有TR1 extensions [wikipedia.org],unordered_map应该有更好的表现......

typedef std::tr1::unordered_map<int,unsigned int> CounterMap;
CounterMap counts;
for (int i = 0; i < numbers.size(); ++i)
{
   CounterMap::iterator it(counts.find(numbers[i]));
   if (it != counts.end()){
      it->second++;
   } else {
      counts[numbers[i]] = 1;
   }
}

答案 1 :(得分:6)

如何使用地图,其中键是您要跟踪的数字,值是出现次数?

如果你必须使用矢量,你已经对它进行了排序。所以只需跟踪您之前看到的数字。如果它与当前数字相同,则递增计数器。每次号码更改时:打印出当前号码和计数,重置计数,将last_seen号码设置为新号码。

答案 2 :(得分:3)

使用地图是实用解决方案。你应该做的是解决这个问题:)

这称为频率计数器。所以,你有一个有序矢量,所有你需要做的就是计算连续相等的数字。换句话说,您必须检查每个号码及其后继号码。

for(size_t i = 0; i < numbers.size(); i++)
{
    size_t count = 1;

    size_t limit = numbers.size() - 1;
    while(i < limit  && numbers[i] == numbers[i+1])
    {
        count++;
        i++;
    }

    std::cout << numbers[i] << "\t" << count << std::endl;
}   

答案 3 :(得分:1)

  

该程序读取数字字符串   从txt文件中,将它们转换为   整数,将它们存储在矢量中,以及   然后尝试输出它们   如此有组织的时尚.... (强调添加)

此存储步骤的重点是什么?如果您正在读取文件中的数字,那么您已经按顺序将它们编号,准备好在遇到它们时一次处理(计数)。

  

但是,我需要一种方法让它知道什么时候会看到一个新号码。

我建议您查看std::setstd::map。我希望这些容器中的任何一个都可以满足您的需求。

答案 4 :(得分:1)

Std::count()非常适合这项法案。

std::vector<int>::const_iterator cur = numbers.begin();
std::vector<int>::const_iterator last = numbers.end();
while (cur != last) {
    unsigned cnt = std::count(cur, last, *cur);
    std::cout << *cur;
    if (cnt != 1) {
        std::cout << " " << c;
    }
    std::cout << std::endl;
    int saved = *cur;
    while (*cur == saved) {
        ++cur;
    }
}

当然还有很多其他算法可以完成同样的工作。与std::equal_range()一起玩std::distance()之类的东西就可以很好地完成工作。

答案 5 :(得分:0)

这很有趣:

#include <map>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>

struct IncrementMap
{
    IncrementMap(std::map<int,int>& m): m_map(m)    {}
        void operator()(int val) const
    {
        ++m_map[val];
    }
    std::map<int,int>& m_map;
};
struct SpecialPrint
{
    SpecialPrint(std::ostream& s):  m_str(s)    {}
    void operator()(std::map<int,int>::value_type const& value) const
    {
        m_str << value.first;
        if (value.second != 1)
        {
            m_str << "\t" << value.second;
        }
        m_str << "\n";
    }
    std::ostream&   m_str;
};
int main()
{
    std::fstream        x("Plop");
    std::map<int,int>   data;

    std::for_each(  std::istream_iterator<int>(x),
                     std::istream_iterator<int>(),
                     IncrementMap(data)
                );
    std::for_each(  data.begin(),
                    data.end(),
                    SpecialPrint(std::cout)
                );
}