【问题标题】:Creating a vector of indices of a sorted vector [duplicate]创建排序向量的索引向量[重复]
【发布时间】:2014-11-13 07:51:48
【问题描述】:

变量xn 整数的向量,我想按升序对向量进行排序。但是,由于此问题范围之外的原因,我希望保持不变。因此,我不想实际对x 的内容进行排序,而是想创建另一个n 索引向量,其中每个索引引用x 中的相应值,如果要对x 进行排序。

例如:

std::vector<int> x = {15, 3, 0, 20};
std::vector<int> y;
// Put the sorted indices of x into the vector y
for (int i = 0; i < 4; i++)
{
    std::cout << y[i];
}

应该给出输出:

2
1
0
3

对应x中的值:

0
3
15
20

我可以想到很多及时的方法来实现这个,但我想知道 STL 是否有内置的东西可以为我有效地执行这个?

【问题讨论】:

标签: c++ stl


【解决方案1】:

x 的所有索引填充y,然后在y 上使用std::sort,但提供一个比较器来比较x 中的相应元素:

  std::vector<int> y(x.size());
  std::iota(y.begin(), y.end(), 0);
  auto comparator = [&x](int a, int b){ return x[a] < x[b]; };
  std::sort(y.begin(), y.end(), comparator);

【讨论】:

    【解决方案2】:

    您可以对另一个列表进行排序,然后与未排序列表进行比较,然后在第三个列表中存储索引,即nlog(n) + n^2 或只是O(n^2)

    注意:这是伪代码

    vector<int> x = {15, 3, 0, 20};
    vector<int> y = sort(x);
    vector<in> z;
    for(int i = 0; y < y.size(); i++){
       for(int j = 0; j < y.size(); j++){
          if(y[i] == x[j]){
             z.push_back(j);
          }
       }
    }
    

    【讨论】:

      【解决方案3】:

      1)创建y作为索引向量(整数范围)

      2) 使用返回来自x 的索引元素的比较器对该范围进行排序 使用标准库,这给出了:

      #include <iostream>
      #include <vector>
      #include <algorithm>
      
      int main() {
      
          std::vector<int> x = {15, 3, 0, 20};
      
          std::vector<int> y;
      
          std::vector<int> y(x.size());
          std::size_t n(0);
          std::generate(std::begin(y), std::end(y), [&]{ return n++; });
      
          std::sort(  std::begin(y), 
                      std::end(y),
                      [&](int i1, int i2) { return x[i1] < x[i2]; } );
      
          for (auto v : y)
              std::cout << v << ' ';
      
          return 0;
      }
      

      Live demo.

      【讨论】:

      • 感谢现场演示的链接——不知道那个网站!
      • 还有很好的 lambda 示例。
      • 如果将数组更改为 {15, 3, 0, 20, 2, 77} 则不正确
      • @sh1ng 我看到了正确的输出,参见here:你看到了什么错误?
      • 惊人的把戏!您使用查看值数组的比较器对索引数组进行排序:)
      【解决方案4】:

      您可以提供自己的 Comparator 来检查目标向量的值,同时对索引向量进行排序,如下所示:

      #include <vector>
      #include <iostream>
      #include <algorithm>
      
      struct IdxCompare
      {
          const std::vector<int>& target;
      
          IdxCompare(const std::vector<int>& target): target(target) {}
      
          bool operator()(int a, int b) const { return target[a] < target[b]; }
      };
      
      int main()
      {
          std::vector<int> x = {15, 3, 0, 20};
          std::vector<int> y;
      
          // initialize indexes
          for(size_t i = 0; i < x.size(); ++i)
              y.push_back(i);
      
          std::sort(y.begin(), y.end(), IdxCompare(x));
      
          std::cout << "\nvector x: " << '\n';
          for(size_t i = 0; i < x.size(); ++i)
              std::cout << x[i] << '\n';
      
          std::cout << "\nvector y: " << '\n';
          for(size_t i = 0; i < x.size(); ++i)
              std::cout << y[i] << '\n';
      
          std::cout << "\nvector x through y: " << '\n';
          for(size_t i = 0; i < x.size(); ++i)
              std::cout << x[y[i]] << '\n';
      }
      

      输出:

      vector x: 
      15
      3
      0
      20
      
      vector y: 
      2
      1
      0
      3
      
      vector x through y: 
      0
      3
      15
      20
      

      【讨论】:

        【解决方案5】:

        我们可以直接采用“引用”方法,并使用指向源向量中值的指针数组。

        #include <iostream>
        #include <vector>
        #include <algorithm>
        
        int main(int argc, const char * argv[]) {
            //a source vector, who's order shouldn't be changed
            std::vector<int> values = {15, 4, 20, 25, 0, 19, -5};
            //a vector of pointers to the values in the source vector
            std::vector<int *> pointersToValues;
            pointersToValues.reserve(values.size());
        
            for(auto& value : values){
                pointersToValues.push_back(&value);
            }
        
            //two comparators in form of lambda functions
            auto descendingOrderSorter = [](int * i, int * j){
                return *i > *j;
            };
        
            auto ascendingOrderSorter = [](int * i, int * j){
                return *i < *j;
            };
        
            //examples of usage
            std::cout<<"Sorting in a descending order"<<std::endl;
            std::sort( pointersToValues.begin(), pointersToValues.end(), descendingOrderSorter);
            for(int i = 0; i < pointersToValues.size(); ++i) {
                std::cout << "index: " << i << ", value: " << *pointersToValues[i] << std::endl;
            }
        
            std::cout<<"Sorting in an ascending order"<<std::endl;
            std::sort( pointersToValues.begin(), pointersToValues.end(), ascendingOrderSorter);
            for(int i = 0; i < pointersToValues.size(); ++i) {
                std::cout << "index: " << i << ", value: " << *pointersToValues[i] << std::endl;
            }
        
            return 0;
        }
        

        pointersToValues[i] 会给你一个指向原始值的指针,*pointersToValues[i] 会给你这个值。

        【讨论】:

          猜你喜欢
          • 2010-10-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-06-21
          • 1970-01-01
          • 1970-01-01
          • 2018-04-20
          相关资源
          最近更新 更多