【问题标题】:Sorting two arrays depending on the values of one array using STL使用 STL 根据一个数组的值对两个数组进行排序
【发布时间】:2016-01-14 14:33:01
【问题描述】:

我想对两个数组a[]b[] 进行排序,但问题是我想同时对ab 进行排序,但仅取决于数组a[] 的值。 使用 STL 的比较函数应该是什么?

a[5] = {4,5,2,10,1};
b[5] = {3,5,2,43,32};

升序排序后:

a[5] = {1,2,4,5,10};
b[5] = {32,2,3,5,43};

我的意思是我不想对第二个数组进行排序,而是希望它随着第一个数组的变化而变化。我想使用 STL。代码会是什么样子?我可以不用 STL。

【问题讨论】:

    标签: c++ sorting stl


    【解决方案1】:

    可以创建第三个指针数组,a+0到a+length-1,使用只需要知道a[]中元素类型的比较,根据a[]对指针进行排序,然后根据指针数组重新排序 a[] 和 b[](在 O(n) 时间内)。

    int a[8] = {7,5,0,6,4,2,3,1};
    char b[8] = {'h','f','a','g','e','c','d','b'};
    int *pa[8];
    size_t i, j, k;
    int ta;
    char tb;
        // create array of pointers to a[]
        for(i = 0; i < sizeof(a)/sizeof(a[0]); i++)
            pa[i] = a + i;
        // sort array of pointers to a[]
        std::sort(pa, pa+sizeof(a)/sizeof(a[0]), compare);
        // reorder a[] and b[] according to the array of pointers to a[]
        // also reverts array of pointers back to a, a + size-1
        for(i = 0; i < sizeof(a)/sizeof(a[0]); i++){
            if(i != pa[i]-a){
                ta = a[i];
                tb = b[i];
                k = i;
                while(i != (j = pa[k]-a)){
                    a[k] = a[j];
                    b[k] = b[j];
                    pa[k] = a + k;
                    k = j;
                }
                a[k] = ta;
                b[k] = tb;
                pa[k] = a + k;
            }
        }
    
    // ...
    
    bool compare(const int *p0, const int *p1)
    {
        return *p0 < *p1;
    }
    

    您还可以使用索引 0 到长度为 1 的数组,并使用 Lambda 比较根据 a[] 比较索引。此示例使用 A[]、B[] 和 I[]:

    int A[8] = {7,5,0,6,4,2,3,1};
    char B[8] = {'h','f','a','g','e','c','d','b'};
    int I[8] = {0,1,2,3,4,5,6,7};
    int tA;
    char tB;
        // sort array of indices to A[]
        std::sort(I, I + sizeof(I)/sizeof(I[0]),
            [&A](int i, int j) {return A[i] < A[j];});
        // reorder A[] and B[] according to the array of indices to A[]
        // also restores I[] back to 0 to size-1
        for(int i = 0; i < sizeof(A)/sizeof(A[0]); i++){
            if(i != I[i]){
                tA = A[i];
                tB = B[i];
                int j;
                int k = i;
                while(i != (j = I[k])){
                    A[k] = A[j];
                    B[k] = B[j];
                    I[k] = k;
                    k = j;
                }
                A[k] = tA;
                B[k] = tB;
                I[k] = k;
            }
        }
    

    【讨论】:

      【解决方案2】:

      这并不完全是微不足道的,但这会奏效。这使用了 C++11 特性。

      #include <vector>
      #include <algorithm>
      
      template<typename A1, typename A2> void sort_base(A1 begin1, A1 end1, A2 begin2)
      {
      
           // deduce types of element values
      
           auto t1 = *begin1;
           auto t2 = *begin2;
           typedef decltype(t1) T1;
           typedef decltype(t2) T2;
           typedef std::pair<T1, T2> P;
      
           // copy and pack the data so we can sort it
      
           std::vector<P> temp(std::distance(begin1, end1));
      
           std::transform(begin1, end1, begin2, temp.begin(),
                [](const T1 &x, const T2 &y) {return std::make_pair(x,y);});
      
           std::sort(temp.begin(), temp.end(),
               [](const P &x, const P &y) {return x.first < y.first;});
      
           //   sorting done.  Unpack the data
      
           std::transform(temp.begin(), temp.end(), begin1,
               [](const P &x) {return x.first;});
      
           std::transform(temp.begin(), temp.end(), begin2,
               [](const P &x) {return x.second;});
      }
      
      int main()
      {
          int a[5] = {4,5,2,10,1};
          double b[5] = {3,5,2,43,32};
      
          // output the arrays however you choose
      
          sort_base(std::begin(a), std::end(a), std::begin(b));
      
          // output the arrays however you choose
      }
      

      sort_base() 函数(我从空中提取的一个名称)确实假定以 begin2 开头的范围(至少)与范围 (begin1, end1) 中的数字相同。

      【讨论】:

        猜你喜欢
        • 2022-12-18
        • 2015-04-17
        • 2015-08-05
        • 1970-01-01
        • 2011-10-09
        • 1970-01-01
        • 2023-02-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多