【问题标题】:Sorting one array based on another in place [duplicate]基于另一个数组对一个数组进行排序[重复]
【发布时间】:2015-11-27 14:59:10
【问题描述】:

我正在使用 C++(使用 c++11 标准)进行编码,并且我有两个内置类型的大数组,我想根据第一个对第二个进行排序。 这是一个例子:

A = {1, 5, 4, 3, 6, 2};
B = {1, 2, 3, 4, 5, 6};

排序后:

A = {1, 2, 3, 4, 5, 6};
B = {1, 6, 4, 3, 2, 5};

就好像每个元素 B[i] 都附加到元素 A[i] 上,而您只需对数组 A 进行排序。所以B 中的元素会根据A 中的对应元素移动。我知道这个问题被问了一遍又一遍,但我遇到的唯一解决方案是使用pair<type 1, type 2>。但是考虑到数组很大,为pair数组分配内存并来回复制数组需要相当长的时间。 但我相信排序可以就地完成,即仅使用O(1) 内存。事实上,如果 std::sort 允许进行服装交换,那就没问题了。因为我认为这是排序算法使用的比较器之外唯一的东西。

A = vector<double>(1e6);  // some random numbers
B = vector<double>(1e6);  // some random numbers
Comp comp(&A,&B);
Swap swap(&A,&B);
costume_sort(A,B,comp,swap);   // some sort function that can take costume swap and compare

class Comp {
   vector<double> *A;
   vector<double> *B;
   Comp(vector<double> *A, vector<double> *B) : A(A),B(B) {};

   bool compareTo(size_t i, size_t j) { return A->at(i) < A->at(j); };
};


class Swap {
   vector<double> *A;
   vector<double> *B;
   Swap(vector<double> *A, vector<double> *B) : A(A),B(B) {};

   void swapFnc(size_t i, size_t j) { swap(A->at(i), A->at(j));swap(B->at(i), B->at(j)); };
};

STL 或其他可用库中是否有任何功能可以做到这一点?这是我试图在这里解释的想法的一种伪代码。显然这并不准确,但我希望我的意思很清楚。

【问题讨论】:

  • @LeFlou 我在更新的问题中提供了一个示例。就像你对 A 进行排序,B 的每个元素都附加到 A 中的相应元素。(B 中的元素 i 附加到 A 中的元素 i
  • 你真的希望两个向量都是double吗?还是一个double 和一个std::size_t
  • @GuyGreer 实际上现在我正在处理一个 double 一个 uint64_t 。但我希望我可以忽略一个是整数的事实,并以更通用的方式编写代码。但是,如果有一个仅适用于整数的巧妙解决方案,我也很高兴知道这一点。
  • 看看stackoverflow.com/a/32720638/1566221,它使用了标准库中提议添加的参考实现。
  • 考虑一张std::pair的表,或者更好的std::tupple

标签: c++ arrays sorting c++11 bigdata


【解决方案1】:

您可以根据类似于相关帖子的索引进行排序:std::sort and custom swap function

它不是一个自定义的交换函数,分配了更多的内存,但性能应该不错。

如果您正在定义类型,那么您可以重载 std::swap 来做您想做的事情:How to overload std::swap()

【讨论】:

  • 这似乎是一个基于链接的答案,你能用你的话解释一下如何更详细地应用这些链接中的信息来解决这个问题吗?
  • Ut nag' melieer nad std::sort ut menik na'g。 Funk kan std::sort nei 'ek lut std::swap merk。重载 mik ut melieit std::swap nak din klas, ut menik nag' mirk talut。
【解决方案2】:

不,没有满足您要求的std:: 函数。

虽然可以提供其自定义的comparison (so Q&A)swap (so Q&A) 函子,但它们对要比较或交换的项目进行(恒定)引用,而不是假设容器上的索引。事实上,这些函子应该对非包含对象的比较和交换有意义。

【讨论】:

    【解决方案3】:

    根据指向 a[] 的指针的排序数组重新排序 a[] 和 b[] 的示例。由于使用了一个指针数组,比较函数只需要知道被比较元素的类型。就地代码重新排序的时间复杂度为 O(n),每个商店都会在其排序位置放置一个值。请注意,指针数组在重新排序期间会恢复到其原始状态 (&a[0] ... &a[n-1])。

    bool compare(const int *p0, const int *p1)
    {
        return *p0 < *p1;
    }
    
    int main()
    {
    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[]
        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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-25
      • 2017-09-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多