尝试基于另一个向量对一个向量进行排序时不一致

时间:2018-03-30 06:02:51

标签: c++ sorting c++11

在下面的C ++代码中,我试图使用sort函数根据另一个向量排序一个向量。例如,如果v1 = (1, 2, 3, 4, 5)v2 = (-1.1, 1.5, 0.2, 4, 3),则在调用我的函数relative_sort (v1,v2)后,我们应该v1 = (1, 3, 2, 5, 4)。我不明白为什么代码无法正常运行。

#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
void print_vector (vector<double> & v)
{
    for (int i = 0 ; i < v.size() ; i++)
        cout << v[i] << ' ' ;
}
void relative_sort (vector<double> & v1 , vector<double> & v2) // sort v1 based on v2
{

    int n = v1.size();
    if ( n != v2.size())
        cout << endl << "Error: The length of v1 is not the same as v2" << endl ;
    else if (n<1)
        cout << endl<< "Error: Empty Vectors" << endl ;
    else
        {
            std::sort(v1.begin(), v1.end(), [&v2](int a, int b) { return v2[a] < v2[b]; } );
        }
}
////////////////////////////////////////////////////////////////////////////////
int main()
{
    vector <double> v2 ;
    vector <double> v1 ;
    vector <double> v0 ;
    double a[] = {0,1,2,3,4};
    v0.assign(a,a+5);
    double b[] = {1,2,3,4,5};
    v1.assign(b,b+5);
    double c[] = {-1.1 , 1.5 , 0.2 , 4, 3};
    v2.assign(c,c+5);

    cout << endl << "V0: " ;
    print_vector(v0) ;
    cout << endl << "V1: " ;
    print_vector(v1) ;
    cout << endl << "V2: " ;
    print_vector(v2) ;
    cout << endl ;

    relative_sort (v0 , v2);

    cout << endl << "V0: " ;
    print_vector(v0) ;

    relative_sort (v1 , v2);

    cout << endl << "V1: " ;
    print_vector(v1) ;

    return 0;
}

上述代码的输出是

V0: 0 1 2 3 4 
V1: 1 2 3 4 5 
V2: -1.1 1.5 0.2 4 3 

V0: 0 2 1 4 3 
V1: 5 2 1 4 3 

v0的输出正确,但不适用于v1。它似乎只适用于v0,而不适用于任何其他矢量!

1 个答案:

答案 0 :(得分:2)

您的代码具有未定义的行为,因为v1的所有值都不是v2的有效索引。特别是,5v2的无效索引。

这是一种完成你想要的方式:

  1. 创建从std::vector<std::pair<double, double>>v1创建的v2
  2. 使用该对中的第二个对新对象进行排序。
  3. 从已排序的向量中拉出值并将它们分配给v1
  4. 这是该功能的更新版本。

    void relative_sort (vector<double> & v1 , vector<double> & v2) // sort v1 based on v2
    {
       size_t n = v1.size();
       if ( n != v2.size())
          cout << endl << "Error: The length of v1 is not the same as v2" << endl ;
       else if (n<1)
          cout << endl<< "Error: Empty Vectors" << endl ;
       else
       {
          std::vector<std::pair<double, double>> v3(n);
          for ( size_t i = 0; i < n; ++i )
          {
             v3[i] = {v1[i], v2[i]}
          }
    
          std::sort(v3.begin(), v3.end(), [](std::pair<double, double> a,
                                             std::pair<double, double> b)
                                          { return a.second < b.second; } );
    
          for ( size_t i = 0; i < n; ++i )
          {
             v1[i] = v3[i].first;
          }
       }
    }
    

    您可以使用boost::zip_iterator来简化该任务,但我自己并没有使用它。

    更新,以回应OP的评论。

    如果您将v1更改为std::vector<size_t>类型而不是std::vector<double>并确保其中包含{0, 1, 2, 3, 4},那么您可以使用:

    std::sort(v1.begin(), v1.end(),
             [&v2](size_t a, size_t b) { return v2[a] < v2[b]; } );
    

    对索引进行排序没有问题。

    您还可以更新自己的功能,以便调整v1的大小以匹配v2的大小,并确保在调用sort之前正确设置索引。

    // Get sorted indices in v1 based on values in v2
    void relative_sort (vector<size_t> & v1 , vector<double> & v2)
    {
       size_t n = v2.size();
       if (n<1)
          cout << endl<< "Error: Empty Vectors" << endl ;
       else
       {
          v1.resize(n);
          for ( size_t i = 0; i < n; ++i )
          {
             v1[i] = i;
          }
    
          std::sort(v1.begin(), v2.end(),
                    [&v2](size_t a, size_t b) { return v2[a] < v2[b]; } );    
       }
    }