【问题标题】:Finding smallest values of given vectors查找给定向量的最小值
【发布时间】:2011-02-18 22:03:48
【问题描述】:

如何有效地找到给定向量集中每一列的最小值?

例如,考虑以下程序:

#include <iostream>
#include <vector>
#include <iterator>
#include <cstdlib>
using namespace std; 

typedef vector<double> v_t;

int main(){

v_t v1,v2,v3;

for (int i = 1; i<10; i++){
 v1.push_back(rand()%10);
 v2.push_back(rand()%10);
 v3.push_back(rand()%10);
}

copy(v1.begin(), v1.end(), ostream_iterator<double>(cout, " "));
  cout << endl;
copy(v2.begin(), v2.end(), ostream_iterator<double>(cout, " "));
  cout << endl;
copy(v3.begin(), v3.end(), ostream_iterator<double>(cout, " "));
  cout << endl;
}

让输出为

3 5 6 1 0 6 2 8 2 
6 3 2 2 9 0 6 7 0 
7 5 9 7 3 6 1 9 2 

在这个程序中,我想找到每列(3 个给定向量)的最小值并将其放入向量中。在这个程序中,我想定义一个向量v_t vfinal,它将具有以下值:

3 3 2 1 0 0 1 7 0

有没有一种有效的方法来做到这一点?我提到高效是因为我的程序可能必须在大量向量中找到最小值。谢谢你。

更新:

我正在尝试使用我在以前的一个程序中使用过的类似的东西

int count = std::inner_product(A, A+5, B, 0, std::plus<int>(), std::less<int>());

这会计算两个数组 A 和 B 之间的最小元素的数量。如果我可以循环并使用类似的函数来查找最小值,这不是足够有效吗?我并不是说它可以完成或不能完成。这只是一个可以改进的想法,但我不知道如何。

【问题讨论】:

  • 如果您关心的是效率,您应该考虑按列而不是按行存储表格。

标签: c++ vector


【解决方案1】:

您可以为此使用std::transform。循环仍然存在,它们只是隐藏在算法中。要处理的每个附加向量都是对std::transform 的调用。

这会在两个线性通道中解决您的示例问题。

typedef std::vector<double> v_t;

int main()
{
    v_t v1,v2,v3,vfinal(9); // note: vfinal sized to accept results

    for (int i = 1; i < 10; ++i) {
        v1.push_back(rand() % 10);
        v2.push_back(rand() % 10);
        v3.push_back(rand() % 10);
    }

    std::transform(v1.begin(), v1.end(), v2.begin(), vfinal.begin(), std::min<double>);
    std::transform(v3.begin(), v3.end(), vfinal.begin(), vfinal.begin(), std::min<double>);
}

注意:这适用于 MSVC++ 2010。我必须为 gcc 4.3 提供 min 函子。

【讨论】:

  • 如果只有三个向量,这看起来很简单。但正如我在问题中所说,如果我必须处理数百个呢?
  • @Sunil:您可以向std::transform 添加另一个调用,就像我的代码中针对每个附加向量的第二个调用一样。向量是像示例中的v1,v2,v3 一样独立,还是在向量容器中?您可以遍历一个向量容器,为每个向量调用std::transform,将结果累积到vfinal
  • 它们是独立的,但我明白了。谢谢。
【解决方案2】:

我认为你的问题的下限是O(n*m),其中n 是向量的数量,m 是每个向量的元素。

我认为,简单的算法(比较不同向量的相同索引处的元素)尽可能高效。

实现它的最简单方法是将所有向量放入某个数据结构(一个简单的类 C 数组,或者可能是向量的向量)。

【讨论】:

    【解决方案3】:

    做到这一点的最佳方法是使用向量的向量,并且只是简单的循环。

    void find_mins(const std::vector<std::vector<int> >& inputs, std::vector<int>& outputs)
    {
        // Assuming that each vector is the same size, resize the output vector to 
        // change the size of the output vector to hold enough.
        output.resize(inputs[0].size());
    
        for (std::size_t i = 0; i < inputs.size(); ++i)
        {
            int min = inputs[i][0];
            for (std::size_t j = 1; j < inputs[i].size(); ++j)
                if (inputs[i][j] < min) min = inputs[i][j];
            outputs[i] = min;
        }
    }
    

    【讨论】:

      【解决方案4】:

      要找到向量中的最小数字,您只需依次检查每个元素;至少从算法的角度来看,没有更快的方法。

      就实际性能而言,缓存问题可能会影响您。正如评论中提到的那样,如果您可以按列而不是按行存储向量,它可能会更有效地缓存。或者,您可能希望并行执行所有最小搜索,以最大程度地减少缓存未命中。即,而不是这个:

      foreach (col)
      {
          foreach (row)
          {
              x_min[col] = std::min(x_min[col], x[col][row]);
          }
      }
      

      你应该这样做:

      foreach (row)
      {
          foreach (col)
          {
              x_min[col] = std::min(x_min[col], x[col][row]);
          }
      }
      

      请注意,STL 已经提供了一个很好的函数来执行此操作:min_element()

      【讨论】:

      • min_element 找到容器中的最小元素,因此它无法执行 OP 想要的操作(除非他选择以其他方式存储元素)。
      • @oli:我在想 peoro 在说什么。 min_element() 仅在必须逐行比较元素时才有用,对吗?排序对我来说很重要,在处理大量向量时,将行更改为列并返回会消耗大量空间和时间。
      • @Sunil:如果您无法修改数据布局,那么您应该考虑并行执行所有最小元素搜索。
      • @Oli:我明白了。这就是我的想法,并试图看看我是否可以使用任何解决方法来克服嵌套的 for 循环。也请看我的问题。我已经更新了它。谢谢
      • @Sunil:你为什么关心嵌套的 for 循环?如果纯粹从代码清晰的角度来看,我相信您可以找到一种使用 STL 迭代器函数来整理它的方法。如果从效率的角度来看,那我就不用担心了。循环逻辑对现代 CPU 的影响应该很小。
      猜你喜欢
      • 2015-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多