【问题标题】:Finding Mode of Vector of Ints in C++C++中整数向量的查找模式
【发布时间】:2011-07-23 06:23:36
【问题描述】:

所以我正在尝试制作一个基本程序来学习 C++ 的基础知识,我正在生成 100 个从 0 到 100 的随机数并将它们存储在一个向量中,然后我将显示总和、平均值、中位数、众数, 向量的高和低。除了卡住的模式之外,我已经完成了所有其他工作。这是我到目前为止的代码。

int modeFunction()
     {
         numMode = 0;
         count = 0;
         for (int n = 0; n < 100; n++)
         {
             for (int y = 0; y < 100; y++)
             {
                 if (numVector.at(y) == numVector.at(n))
                {
                    numMode = numVector.at(y);
                    count++;
                }
             }

         }
         return numMode;
     }

在那之后我被卡住了,因为在我看来这应该有效,但它没有。它只是输出最后一个数字,通常是 100。任何帮助将不胜感激。

【问题讨论】:

  • 如果myVectorstd::vector&lt;int&gt;(至少看起来像),您可以像数组一样对其进行索引:myVector[y]myVector[n] 将产生与myVector.at 版本相同的结果,但看起来更好恕我直言。 :)
  • @Xeo:区别在于at 定义了索引超出范围时的行为。可以说operator[] 是一个微优化,尽管正如你所说,它也有点风格差异。
  • @Steve:啊,谢谢你的花絮。 :) 还没有打扰at,但是普通数组对于超出范围的访问也有未定义的行为,尽管在需要时定义行为当然很好。 :)
  • @Xeo:说实话,我自己从不使用at。我偶尔想知道我是否应该,但实际上我从不编写我想在索引超出范围时抛出异常的代码,所以它只是作为调试辅助,它“应该”永远不会发生。尽管称其为微优化,但它是合理数量的冗余代码,所以最后如果我想要边界检查,我只需切换到 Python ;-)

标签: c++ function random vector mode


【解决方案1】:

由于所有值都在 0 到 100 之间,因此您可以使用直方图有效地找到模式:

std::vector<int> histogram(101,0);
for( int i=0; i<100; ++i )
  ++histogram[ numVector[i] ];
return std::max_element( histogram.begin(), histogram.end() ) - histogram.begin();

【讨论】:

  • 这是否不适用于 [0,100] 之外的值(这应该适用于任何对称直方图,不是吗?)
【解决方案2】:

由于 mode 是出现频率最高的数字,因此您不应更改 numMode,除非新数字的计数大于 numMode 的计数。

编辑:为了澄清,您需要为当前元素和您认为是模式的当前数字保留单独的计数。理想情况下,将newMode 设置为第一个元素是一种好方法。

此外,模式不一定是唯一的(即“1 1 2 2”)。如果您关心这一点,您可能需要牢记这一点。

newMode = element[0]
modeCount = # of occurrence of newMode

for ( i-th element from [1 to end] ) {
   tmpCount = # of occurrence of element[i]
   if tmpCount > modeCount {
     newMode = element[i]
     modeCount = tmpCount
   }
}

【讨论】:

  • 我是投反对票的人。我这样做是因为这个答案是不完整的,因为它假设值的出现次数数组是已知的,但是,这个数组在这里是最重要的。
【解决方案3】:

如果元素数量足够少,bmcnett 的方法效果很好。如果您有大量元素,但所有元素值都在一个小范围内,则使用 map/hashmap 效果很好。像

typedef std::pair<int, int> mode_pair;

struct mode_predicate
{
  bool operator()(mode_pair const& lhs, mode_pair const& rhs)
  {
    return lhs.second < rhs.second;
  }
};

int modeFunction()
{
  std::map<int, int> mode_map;
  for (int n = 0; n < 100; n++)
    mode_map[numVector[n]]++;
  mode_predicate mp;
  return std::max_element(mode_map.begin(), mode_map.end(), mp)->first;
}

【讨论】:

    【解决方案4】:

    您的算法是错误的 - 它输出数组中的最后一个数字,因为这就是它所能做的一切。每次索引y 处的数字与索引n 处的数字匹配时,您都会覆盖前一个n 的结果。由于您使用相同的循环条件,yn总是对于每个可能的 n 值,在嵌套循环中的至少一个点上是相同的 - 你将永远最终以 numModenumVector.at(99)

    您需要更改算法以保存沿途每个n 索引的计数(或至少哪个n 索引以最大count 结束),以便您可以知道在最后出现次数最多的 n 循环。

    【讨论】:

      【解决方案5】:

      替代解决方案。注意:未经测试。

      int mode1(const std::vector<int>& values)
      {   
          int old_mode = 0;
          int old_count = 0;
          for(size_t n=0; n < values.size(); ++n) 
          {
              int mode = values[n];
              int count = std::count(values.begin()+n+1, values.end(), mode);
      
              if(count > old_count) 
              {
                  old_mode = mode;
                  old_count = count;
              }
          }
          return old_mode;
      }
      
      int mode2(const std::vector<int>& values)
      {   
          return std::max_element(values.begin(), values.end(), [](int value)
          {
              return std::count(values.begin(), values.end(), value);
          });
      }
      

      【讨论】:

      • 我认为在mode1() 中你应该将count + 1old_count 进行比较,因为你从计数值位置之后的第一个位置开始计数:即你必须将初始值添加到@987654325 @.
      • 此外,我认为将搜索属性的值的初始值分配为0 并不是一个好习惯。为此最好使用第一个元素。
      【解决方案6】:

      众数表示频率最高的数字。逻辑应该是 -

      //Start of function
      
      int mode = 0, globalCount = 0 ;  
      // Start of outer for loop
      for i = 0 to length - 1    
         int localCount = 0   
      
        // Start of inner for loop  
        for j = 0 to length - 1      
           if vec[i] == vec[j]    
           ++localCount    
       // End of Inner for loop 
      
       if ( localCount > globalCount )  
           globalCount = localCount  
           mode = vec[i]  
      // End of outer for loop  
      
      if globalCount > 1 // This should be checked whether vec has repetitions at all
         return mode
      else
         return 0
      
      // End of function
      

      【讨论】:

      • @Cistoran - 逻辑可以更好地提高效率,但根据您的思考过程,算法应该是这样的。
      【解决方案7】:
          int number = array_list[0];
          int mode = number;
          int count = 1;
          int countMode = 1;
      
          for (int i=1; i<size_of_list; i++)
          {
                if (array_list[i] == number) 
                { // count occurrences of the current number
                   count++;
                   if (count > countMode) 
                      {
                            countMode = count; // mode is the biggest ocurrences
                            mode = number;
                      }
                }
                else
                { // now this is a different number
                      if (count > countMode) 
                      {
                            countMode = count; // mode is the biggest ocurrences
                            mode = number;
                      }
                     count = 1; // reset count for the new number
                     number = array_list[i];
            }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-12
        • 1970-01-01
        • 2016-08-24
        相关资源
        最近更新 更多