使用标准库根据一个数组对两个数组进行排序(避免复制步骤)

Posted

技术标签:

【中文标题】使用标准库根据一个数组对两个数组进行排序(避免复制步骤)【英文标题】:Sorting two arrays based on one with standard library (copy steps avoided) 【发布时间】:2017-05-17 14:32:46 【问题描述】:

我有旧代码要维护,我正在替换一个自定义 QuickSort,该 QuickSort 使用 std::sort 根据数组 1 对两个数组进行排序。有没有一种方法可以根据其中一个数组对两个数组进行排序,而无需额外的拆分步骤并且无需再次实现排序功能?下面是当前示例 vector1D 基本上是 std::vector。

    vector1D<std::pair<int64_t, uint8_t>> m_RowCol(m_NX * m_NY * m_NZ);
    //..
    std::sort(
        m_RowCol.begin(),
        m_RowCol.end(),
        [](const std::pair<int64_t, uint8_t> &a, const std::pair<int64_t, uint8_t> &b)  return a.first < b.first && (a.first > 0 && b.first > 0); 
    );
    // copy into two vectors
    vector1D<int64_t> m_Row;
    vector1D<uint8_t> m_Col;
    for (auto it = std::make_move_iterator(m_RowCol.begin()), end = std::make_move_iterator(m_RowCol.end()); it != end; ++it)
    
        m_Row.push_back(std::move(it->first));
        m_Col.push_back(std::move(it->second));
    
    m_RowCol.clear(); 

【问题讨论】:

见***.com/questions/13840998/… 请注意,尽管您的比较器不满足严格的弱排序要求,但您的程序会表现出未定义的行为。具体来说,0等价于1,0等价于2,但1不等价于2。 @Igor 谢谢你 我想避免使用第 3 方库。 Boost 可能会起作用。 你更新的比较器仍然有同样的问题。 【参考方案1】:

您可以创建一个索引数组,根据其中一个数组对索引进行排序,然后在 O(n) 时间内根据排序后的索引数组对两个数组和索引数组重新排序:

#include <algorithm>
#include <iostream>

int main()

int A[8] = 8,6,1,7,5,3,4,2;
char B[8] = 'h','f','a','g','e','c','d','b';
size_t I[8];
size_t i, j, k;
int ta;
char tb;
    // create array of indices to A[]
    for(i = 0; i < sizeof(A)/sizeof(A[0]); i++)
        I[i] = i;
    // 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[] B[] I[] according to I[]
    for(i = 0; i < sizeof(A)/sizeof(A[0]); i++)
        if(i != I[i])
            ta = A[i];
            tb = B[i];
            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;
        
    
    for(i = 0; i < sizeof(A)/sizeof(A[0]); i++)
        std::cout << A[i] << ' ';
    std::cout << std::endl;
    for(i = 0; i < sizeof(B)/sizeof(B[0]); i++)
        std::cout << B[i] << ' ';
    std::cout << std::endl;
    return 0;

或者可以使用指针数组代替索引数组,这样就可以使用普通的比较函数而不是 lambda 比较函数。

#include <algorithm>
#include <iostream>

bool compare(const int *p0, const int *p1)

    return *p0 < *p1;


int main()

int A[8] = 8,6,1,7,5,3,4,2;
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[] B[] pA[] according to pA[]
    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];
        
    
    for(i = 0; i < sizeof(A)/sizeof(A[0]); i++)
        std::cout << A[i] << ' ';
    std::cout << std::endl;
    for(i = 0; i < sizeof(B)/sizeof(B[0]); i++)
        std::cout << B[i] << ' ';
    std::cout << std::endl;
    return 0;

【讨论】:

以上是关于使用标准库根据一个数组对两个数组进行排序(避免复制步骤)的主要内容,如果未能解决你的问题,请参考以下文章

如何对具有动态属性的数组进行排序? [复制]

如何在 C# 中按升序对多维数组进行排序? [复制]

简单的数组排序

Java:就地对 ArrayList 进行排序

JS sort() 按照某个属性对数组进行排序

对一个 observable 数组进行排序,该数组已查询到由微风JS 返回的数据