如何将单独的数组分组在一起(类似于按一列对表进行排序)

How to sort separate arrays together (similar to sorting a table by one column)?

本文关键字:一列 排序 类似于 单独 数组 在一起      更新时间:2023-10-16

给定两个或多个数组,我如何选择对一个数组进行排序并相应地对其他数组进行分类?这类似于按一列对表排序。

int main()
{
    int values1[] = {5, 4, 3, 2, 1};
    double values2[] = {1.0, 2.0, 3.0, 4.0, 5.0};
    std::string values3[] = {"h", "e", "l", "l", "o"};
    // sort by values1
    // values1 = {1, 2, 3, 4, 5};
    // values2 = {5.0, 4.0, 3.0, 2.0, 1.0};
    // values3 = {"o", "l", "l", "e", "h"};
    // sort by values3
    // values1 = {4, 5, 3, 2, 1};
    // values2 = {2.0, 1.0, 3.0, 4.0, 5.0};
    // values3 = {"e", "h", "l", "l", "o"};
}

以下是我提出的一些策略。希望您能给我一些提示。谢谢!

策略1:

  1. 制作结构struct sortstruct{int i; double d; std::string s};
  2. 创建向量和复制值
  3. 编写谓词功能并使用std :: sort
  4. 复制值回到原始结构。

这似乎很容易,但这还涉及重复所有数据两次,并且如果阵列很大,也会创建许多小对象。另外,如果阵列的数量变化,这不是灵活的。

策略2:

  1. 制作数组的副本以与。
  2. 进行排序。
  3. 使用std :: sort。
  4. 对副本进行分类
  5. 通过排序的副本移动并为每个值移动,在原始数组中找到值,然后在所有值数组中交换索引位置。

也很容易实现,但是在未排序的数组中找到值需要二次的时间(每个值的线性时间(。

策略3:

  1. 实现一种自定义排序算法,该算法采用"键"数组并将所有交换应用于其他数组。

我不喜欢我自己做分类。但这当然没有问题,如果这是最好的策略。

最好的解决方案可能是创建一个包含值或使用std::tuple的结构。

如果您不能这样做,则可以引入一层间接指数,即 indices (实际上是查找数组(。
根据您的策略订购它,永远不要更改其他阵列中项目的位置。每当您想获得元素的元素时,从一系列索引中获取第i-th元素,并使用它从所有其他数组中获取正确的值。
如果将来添加越来越多的阵列,只要您将它们隐含地以某种方式与对方进行隐式订购。
当您添加新的元组时,只需在索引数组的末尾推开其他阵列的 size (我认为它们都具有相同的大小(:那将是新的索引元素。然后在需要时再次对索引数组进行排序。
排序功能可能要求您传递具有访问外部阵列的比较函数,但是使用lambdas并通过参考捕获非常简单。

实际上,我建议使用将元素绑定到各个数组的数据结构,例如structtuple

,但是可以利用这样一个事实,即像qsort这样的排序算法使用自定义比较功能来决定是否交换两个值。鉴于此,人们可以定义一个比较函数,除了返回比较结果外,还可以在其他数组中"手动交换"值的意义上具有副作用。

我知道这很丑陋,因为它依赖于对算法qsort进行分类的内部,并且我不确定我是否错过了必不可少的东西(如果有人出于这个原因,我不会哭泣,我不会哭泣(。但是,也许在非常例外的情况下可能会有所帮助:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int values1[] = {5, 4, 3, 2, 1};
double values2[] = {1.0, 2.0, 3.0, 4.0, 5.0};
std::string values3[] = {"h", "e", "l", "l", "o"};
int cmpfunc( const void *a, const void *b) {
    // calculate the array indexes of a and b using pointer arithmetics:
    size_t indexA = ((int*)a - values1);  
    size_t indexB = ((int*)b - values1);
    int result = *(int*)a - *(int*)b;
    if (result > 0) {
        swap(values2[indexA],values2[indexB]);
        swap(values3[indexA],values3[indexB]);
    }
    return result;
}
int main() {
    qsort(values1, 5, (size_t) sizeof(int), cmpfunc);
    return 0;
}

with range-v3,您可以做

ranges::sort(ranges::view::zip(values1, values2, values3),
             std::less<>{},
             [](const auto& t) { return std::get<1>(t);}); // Projection

demo