查找向量中的最小项目列表

时间:2015-11-17 13:42:14

标签: c++ algorithm sorting vector

我有一个矢量示例矢量myVec;

例如,我的矢量中有100个元素。现在我想迭代100个元素并找到向量中可能的10个最小元素。

//执行此操作的一种方法是使用sort algoritm按顺序对矢量项进行排序,并获取前10项。然后在这里我必须创建另一个矢量来存储原始和排序的矢量。这里的原始程序需要知道向量中每个10的sortest值的行号 - 这是我程序中的那个。

但是现在我需要一个最简单的for循环或while语句来找到向量中的10个最小值而不进行排序?。

4 个答案:

答案 0 :(得分:0)

检查此示例:

// partial_sort example
#include <iostream>     // std::cout
#include <algorithm>    // std::partial_sort
#include <vector>       // std::vector

int main () {
  int myints[] = {9,8,7,6,5,4,3,2,1};
  std::vector<int> myvector (myints, myints+9);

  // using default comparison (operator <):
  std::partial_sort (myvector.begin(), myvector.begin()+5, myvector.end());

  // print out content:
  std::cout << "myvector contains:";
  for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

输出:

myvector contains: 1 2 3 4 5 9 8 7 6

它使用std::partial_sort(如Jarod42所说),它对第一个n值(在您的情况下为10)进行排序,同时将其他值保留为任意顺序。现在你可以修改它来满足你的需求。

答案 1 :(得分:0)

实际上,鉴于您只需要知道10个最小的项目(并且不需要按顺序排列这10个项目),您可以使用std::nth_element代替std::partial_sort。这正是你所要求的,没有什么额外的,所以它很有可能提高效率。

就避免复制输入而言,您可以创建一个索引向量,用于索引到原始数组中,并对索引而不是原始数组进行操作。

一般的想法看起来像这样:

std::vector<foo> input;

// ...

// This is our index. It'll be filled with 0..I (where I = size of input).
std::vector<std::size_t> index(input.size());
std::iota(index.begin(), index.end(), 0);

// This is the number of smallest items we need to find:
const int N = 10;


if (index.size() <= N) // if we have fewer elements, do nothing.
    return;

// sort our index according to the values in the input:
std::nth_element(index.begin(), index.begin() + N, index.end(),
    [&input](size_t a, size_t b) { return input[a] < input[b]; });

// write out the N smallest items of the input.
for (int i = 0; i < N; i++)
    std::cout << input[index[i]] << "\t";

当然,您可以使用指向原始项目而不是索引的指针向量,但是您说您需要“行号”,因此我编写了代码来提供完全相同的内容。

答案 2 :(得分:0)

如果您需要自己编写代码,请使用快速选择来查找第10个最小元素。这会将数组分成几个部分,左边是最小的,第9个最小但是没有排序,第10个最小作为枢轴,右边是元素&gt; =第10个最小元素。维基文章:

http://en.wikipedia.org/wiki/Quickselect

答案 3 :(得分:0)

通常,我建议您使用其他答案中建议的标准库sort,partial_sort,nth_element等。

但是,找到min并不难,避免排序并避免重复矢量,

AND

如果您在要求时确实是指它:

  

我需要一个最简单的for循环或while语句来查找10   矢量中的最小值没有排序?。

这是一种方法:(参见下面的评论“找到10个最小值”)

#include <iomanip>
#include <iostream>
#include <vector>
#include <chrono>
#include <algorithm>  // shuffle

  typedef std::vector< int >     IntVec;
  typedef std::vector< size_t >  IndxVec;

  const size_t SMALLEST_10 = 10;

  void myVecShow(IntVec& intVec, const std::string label); // below


  // ///////////////////////////////////////////////////////
  size_t findIndxOfMinValue(const IntVec& intVec)
  {
     size_t minIndx = 0; // search from beginning

     for (size_t j = 0;
          j < intVec.size();  // compare each
          ++j)
     {
        if(intVec[j] < intVec[minIndx])
           minIndx = j; // capture smallest
     }
     return(minIndx);
  }


  // ///////////////////////////////////////////////////////
  int t258()
  {
     IntVec myVec;

     {
        // fill myVec
        for (int i=0; i<100; ++i)
           myVec.push_back(100-i);    // "my vector for instance has 100 elements in it."

        //myVecShow(myVec, "\n unshuffled values: ");

        // shuffle myVec
        time_t seed = std::chrono::system_clock::now().time_since_epoch().count();
        std::shuffle (myVec.begin(), myVec.end(), std::default_random_engine(seed));

        myVecShow(myVec, "\n Values: ");
     }

     IndxVec indxVec; // to be filled with index of the smallest elements
     indxVec.reserve(SMALLEST_10);

     IntVec  origVal; // capture original values of smallest elements
     origVal.reserve(SMALLEST_10);

     // ///////////////////////////////////////////////////////
     // find 10 smallest values
     {
        for (size_t i=0; i<SMALLEST_10; ++i)
        {
           size_t minValIndx = findIndxOfMinValue(myVec);
           indxVec.push_back (minValIndx);         // capture index
           origVal.push_back (myVec[minValIndx]);  // capture value at index
           myVec[minValIndx] = std::numeric_limits<int>::max(); // mark min value (so its no longer min)
        }
        std::cout << std::endl;
     }

     // restore original values prior to report
     for (size_t i=0; i<indxVec.size(); ++i)
     {
        size_t indx = indxVec[i];
        myVec [indx] = origVal[i];
     }

     // ///////////////////////////////////////////////////////
     // report results
     std::cout << "\nSmallest 10 elements: " << std::endl;
     std::cout << "     indx   value" << std::endl;
     for (size_t i=0; i<indxVec.size(); ++i)
     {
        size_t indx = indxVec[i];
        std::cout << "myVec[" << std::setw(2) << indx
                  << "] = "   << std::setw(3) << myVec[indx]
                  << std::endl;;
     }
     std::cout << std::endl;

     return(0);

  } // int t258(void)


  // ///////////////////////////////////////////////////////
  void myVecShow(IntVec& intVec, const std::string label)
  {
     std::cout << label << std::endl;
     size_t j = intVec.size() - 1;

     // header:
     {
        std::cout << "      ";
        for (size_t i=0; i<SMALLEST_10;  ++i) std::cout << std::setw(3) << i << "   ";
        std::cout << std::endl;
     }

     std::cout << std::setw(3) << 0 << ":  ";

     for (size_t i=0; i<intVec.size(); ++i)
     {
        std::cout << std::setw(3) << intVec[i] << "   ";

        if ((i < j) && (9 == (i % 10)))
        {
           size_t row = 1 + (i / 10);
           std::cout << std::endl << std::setw(3) << row << ":  ";
        }
     }
     std::cout << std::endl;
  }

结果:(随机洗牌)

  Values: 
        0     1     2     3     4     5     6     7     8     9   
  0:   50    85     6    62    48    34    40    73    86    11   
  1:   94    58    46    96    66    56    42    15    25    13   
  2:   92    30     7    35    65    37     5    69    90    68   
  3:  100     3     2    87    21    93    43    99    10    98   
  4:   44    24    70    41    59    95    72    49    78    81   
  5:    4    23    47    51    36    54    12    67    91    14   
  6:   53    97    71    52    77    27    20    29    76    83   
  7:   80    28    17    38    32    16    39     9    74    18   
  8:   84    31    61    45     8    33    82    55    63    89   
  9:   60    26    88    79     1    19    57    75    64    22   


Smallest 10 elements: 
     indx   value
myVec[94] =   1
myVec[32] =   2
myVec[31] =   3
myVec[50] =   4
myVec[26] =   5
myVec[ 2] =   6
myVec[22] =   7
myVec[84] =   8
myVec[77] =   9
myVec[38] =  10

更新 - 当最小的10中的值重复时会发生什么:

我添加了

myVec[6] = 7;

重新运行代码(因此,这是一个不同的随机shuffle),输出是:

Smallest 10 elements: 
     indx   value
myVec[ 7] =   0
myVec[78] =   1
myVec[83] =   2
myVec[79] =   3
myVec[11] =   4
myVec[87] =   5
myVec[12] =   7
myVec[67] =   7
myVec[42] =   8
myVec[51] =   9

更新 - 我们如何修改此代码以显示最小的10个唯一值的索引

注意:未运行测试,并且此第一次尝试代码(可能)无法正确处理少于10个唯一值的100元素数组

 // find 10 smallest **unique** values
 {
    for (size_t i=0; i<SMALLEST_10; ++i)
    {
       size_t minValIndx = findIndxOfMinValue(myVec);
       indxVec.push_back (minValIndx);         // capture index
       origVal.push_back (myVec[minValIndx]);  
       myVec[minValIndx] = std::numeric_limits<int>::max(); 

       // now hide any duplicate of this minValue, 
       for (size_t j=0; j<myVec.size(); ++j)  // search all
       {
          if(myVec[j] == origVal.back()) 
          {
             indxVec.push_back (j);    // capture index
             origVal.push_back (myVec[j]); 
             myVec[minValIndx] = std::numeric_limits<int>::max(); 
          }
       }   
    }
    std::cout << std::endl;
 }