【问题标题】:How to find indexes of 5 the biggest elements in vector?如何找到向量中 5 个最大元素的索引?
【发布时间】:2012-09-17 20:19:40
【问题描述】:

如何找到向量中 5 个最大元素的索引? 比如std::vector<int>如何找到5个最大值的索引而不改变原始向量?

【问题讨论】:

  • 迭代它并将当前值与之前的 5 个最大的值进行比较?那个,或者复制,排序,拿前5。
  • @slugonamission:使用nth_element 比排序要好一点...尽管这比线性遍历容器并维护所见的 5 个最大元素的列表更糟糕
  • @DavidRodríguez-dribeas - 啊哈,我从来不知道。谢谢:)

标签: c++ stl


【解决方案1】:

std::partial_sort( v.begin(), v.begin()+5, v.end() ) 以某种方式对向量进行排序,即 5 个最小值被排序并位于 v 的开头。其余的未排序。

既然您想要索引并保留原始索引:
用 0..n-1 的数字填充一个新向量,并提供一个比较函数,该函数执行 v[a] > v[b] 而不是 a > b

struct Comp{
    Comp( const vector<int>& v ) : _v(v) {}
    bool operator ()(int a, int b) { return _v[a] > _v[b]; }
    const vector<int>& _v;
}

vector<int> vx;
vx.resize(v.size());
for( int i= 0; i<v.size(); ++i ) vx[i]= i;
partial_sort( vx.begin(), vx.begin()+5, vx.end(), Comp(v) );

vx[0..4] 包含索引。

【讨论】:

    【解决方案2】:

    1 解决方案:

    解决方案是 O(n),其中 n 是正在检查的向量中的元素数。

    创建一个长度为 5 的向量迭代器的出队,初始化为 NULL 读取正在检查的向量的元素并 push_back 索引{想法是根据读取的新元素数据是小于后索引的数据还是大于前索引的数据,将新索引推到前面或后面,如果dequeue 中已经存在的数据为 NULL,那么无论你 push_front 还是 push_back,都无所谓}。这将保持从前到后排序的出队。

    如果正在读取的新数据大于前面的数据,则移除后面,将当前数据的迭代器推到前面;否则什么都不做

    在迭代结束时,出队将拥有前五个元素的迭代器。

    【讨论】:

      【解决方案3】:

      您可以从原始向量中复制一份,并使用来自 STL nth_element 的专用算法对其进行部分排序:

      bool cmp (int i,int j) { return (i<j); }    
      int main () {
            vector<int> myvector;
            vector<int>::iterator it;
      
            // set some values:
            for (int i=1; i<10; i++) myvector.push_back(i);   // 1 2 3 4 5 6 7 8 9
      
            random_shuffle (myvector.begin(), myvector.end());
      
            // using default comparison (operator <):
            std::vector<int> copy_of_orig = myvector;
            nth_element (copy_of_orig.begin(), copy_of_orig.begin()+5, copy_of_orig.end(), cmp);
            // Display the first five biggest elts.
            for (int i = 0; i < 5; ++i)
              std::cout << copy_of_orig[i] << std::endl;
      }
      

      【讨论】:

      • OP 要求提供索引,因此您不会复制向量,而是用值 0,...myvector.size()-1(或指向向量元素的指针/迭代器)填充它,您需要进行间接比较
      【解决方案4】:

      可能有一种更优雅的方式,但我现在很难找到它。你可以做这样的事情(未经测试,所以不能保证它开箱即用,特别是在极端情况下,但它应该):

      std::array<int, 5> indices = {-1,-1,-1,-1,-1};//-1 used as invalid index for cases where myVec.size()<5
      for(int i = 0; i < myVec.size(); ++i)
      {
          for(int j = 0; j < 5; ++j)
              if((indices[j] == - 1) || (myVec[i] > myVec[indices[j]]))
              {
                  std::copy_backward(indices.begin() + j, indices.end() - 1, indices.end());
                  indices[j] = i;
                  break;
              }
      }
      

      它维护 5 个最大元素的列表。对于向量的每个元素,它将从最大元素开始,测试新元素是否更大,如果是,则将索引向下移动并作为第一个插入,否则测试第二大元素,依此类推。不修改 vector 并在 O(n) 中以相当低的开销运行。

      如果你不能使用 C++11,你总是可以使用std::vector(或者int[5],如果你真的想要)而不是std::array

      【讨论】:

        【解决方案5】:

        你需要做这样的事情:

          int largestNumbers [5]{0, 0, 0, 0, 0};
        
          for each( const int i in data ){
          {
            for (int index = 0; index < 5; index++){
               if (i > largestNumber[index]){
                  largestNumber[index] = i;
               }
             }
          }
        

        【讨论】:

        • 在我看来这不像 C++。
        • 这段代码有两个问题:1) OP 要求的是索引,而不是值。 2) 对于序列{0,1,2,3,4,5},这将以largestNumbers 结束,即{5,5,5,5,5}
        猜你喜欢
        • 2012-12-17
        • 2015-01-13
        • 1970-01-01
        • 2014-06-28
        • 1970-01-01
        • 2012-12-27
        • 1970-01-01
        • 1970-01-01
        • 2016-06-11
        相关资源
        最近更新 更多