根据另一个数组的顺序对数组进行排序

Sort an array according to the sequence of another array

本文关键字:数组 排序 另一个 顺序      更新时间:2023-10-16

假设我有一个数组A[]={8, 9, 11, 14, 16, 20};,我必须根据另一个数组B[]={6, 5, 1, 2, 4, 3};对其进行排序。

排序的A将是A[]={20, 16, 8, 9, 14, 11};

因此,A将如何排序在B中说明
B的第一元素是最大的,因此A的第一元素也将是最大的。B的第三元素最小,因此A的第三个元素也将最小

如果B是像{100, 84, 74, 51, 5, 1}一样按降序排序的,那么A也将按降序排序
示例:
1.如果B = {12, 8, 14, 156, 2, 84},则A将为{11, 9, 14, 20, 8, 16}
2.如果B = {2, 3, 45, 0, 7, 56},则A将是{9, 11, 16, 8, 14, 20}

就像我有一些不同年龄的朋友,我想根据他们的年龄给他们一些东西。最年长的人会得到最大的一个。。。比他小就会得到比他小的。。等等

我见过类似的问题,但它们不像我的问题
我的想法是先把两者都分类。然后重新排列。

有什么快速的解决方案吗?

在您的第一个示例中,您似乎希望使用索引B数组来置换A。但第二个示例显示,您确实想要排序,但比较基于B中的值,而不是A中的值。

所以你需要的是一个排序函数,它采用"排序键函数"。应将数组索引作为参数传递给排序键函数。

C的qsort确实采用了键函数,但键函数的自变量是被比较的,而不是被比较的值的index。所以它对你不起作用。

您可能需要编写自己的排序函数。这并不难。如果数组很小,简单的插入排序就可以了:

void sort_by_keys(int *values, int *sortkeys, int size)
{
   int i, j;
   for (i = 1; i < size; i++) {
     j = i;
     /* For a usual insertion sort, the condition here
      * would be values[j] < values[j-1]. */
     while (j > 0 && sortkeys[j] < sortkeys[j-1]) {
       swap(values, j, j - 1);
       swap(sortkeys, j, j - 1);
       j--;
     }
   }
}

(您必须编写自己的swap。)

如果数组较大,您可以自己编写递归或迭代快速排序。这也不难。确保您还编写了一些测试用例以确保它能够工作。您的测试用例应该包括空数组和带有1项的数组。

看起来这是一个复制操作,而不是排序。

第二个数组显示了第一个数组元素的排序。差值是从第二个数组中减去1,得到排序数组的偏移量。

const int original_array[]={8, 9, 11, 14, 16, 20};
const int ordering_array[]={6, 5, 1, 2, 4, 3};
int result array[6];
for (unsigned int i = 0;  
     i < sizeof(original_array)/sizeof(original_array[0]);
     ++i)
{
  int source_index = ordering_array[i] - 1;
  result_array[i] = original_array[source_index];
}

如果我正确理解你的问题,你想计算B的排序排列的逆,然后按该顺序对A排序。使用标准库可以很容易地做到这一点。

int A[] = { 8,  9, 11, 14, 16, 20};
int B[] = { 6,  5,  1,  2,  4,  3};
const auto ASIZE = std::extent<decltype(A)>::value;
const auto BSIZE = std::extent<decltype(B)>::value;
// A and B must be the same size
assert(ASIZE == BSIZE);
// p = sorted permutation of B largest to smallest
std::vector<size_t> p(ASIZE);
std::iota(p.begin(), p.end(), 0);
std::sort(p.begin(), p.end(), [&](size_t i1, size_t i2) { return B[i1] > B[i2]; });
// pinv = inverse of p
std::vector<size_t> pinv(ASIZE);
for (size_t i = 0; i < ASIZE; ++i)
    pinv[p[i]] = i;
// Sort A largest to smallest
std::sort(std::begin(A), std::end(A), [&](int v1, int v2) { return v1 > v2; });

然后您可以通过pinv间接获得所需顺序的A

for (size_t index : pinv)
    std::cout << A[index] << " ";
std::cout << std::endl;
// Output is: 20 16 8 9 14 11