使用qsort对多个数组进行排序

时间:2014-02-27 18:25:00

标签: c

我有一个包含多个数组的结构。我需要能够对这些数组中的任何一个进行排序,并根据排序的数组移动其他数组中的元素。

struct arrayset
{
int values1[] = { 32, 10, 101, 72, 13, 5 };
int values2[] = { 40, 10, 100, 90, 20, 2 };
int values3[] = { 16, 14, 93, 2, 37, 39 };
};

我理解如何只使用一个,但我不确定改变其他两个数组中元素的优雅方法。我不是要尝试对其他两个数组进行排序,但我希望这些元素能够继续匹配后期排序,而不是混淆。有什么建议?

qsort(arrayset.values1,6,sizeof(int), compare);
//values2/3 elements would follow values1's elements

3 个答案:

答案 0 :(得分:4)

在必须执行多个独立数据结构的同步重新排列的情况下,您可以遵循以下两种方法之一:

  1. @wallyk提到的一种侵入式“内部”方法 - 即提供你自己的交换函数,它将同步交换所有三个数组中的元素。
  2. 非侵入式“外部”方法 - 将排序过程分解为两个独立的步骤:首先,从“main”数组生成排序排列,然后将排序排列独立地应用于三个数组中的每一个。
  3. 第一种方法可能更容易实现,但它有一些明显的缺点。随着数据集的数量增加和/或元素本身变得更重,交换功能也变得更重。这对于基于元素的物理复制的算法排序来说不是一件好事,因为这样的算法可能会多次重新定位(交换)每个元素。

    第二种方法本质上是基于间接的索引排序,这意味着它对重复元素复制的敏感程度较低。第二种方法只有在知道最终位置时才复制每个实际元素一次。

    要生成排序排列,您只需要使用p初始化的整数 index 数组{ 0, 1, 2, 3, ... }。不是直接排序values1,而是对此索引数组p进行排序,以使其为values1数组生成正确的排序。 (标准qsort函数对于此类应用程序不能很好地工作,因为它是无上下文的。)

    排序后,该索引数组将作为您的排列。您需要做的就是根据排列重新排列三个阵列中的每一个。根据您的需要,它可以就地完成,也可以更容易,不合时宜地完成。

    在您的具体示例中,您将从索引数组

    开始
    p = { 0, 1, 2, 3, 4, 5 }
    

    排序后会变成

    p = { 5, 1, 4, 0, 3, 2 }
    

    这是values1数组的所谓 from-permutation :它告诉您为了获得values1的排序版本,位置{ {1}}应从 i中获取。现在,您需要做的就是使用相同的from-permutation values1[p[i]]生成重新排列的values1values2values3版本。

    同样,后一步很容易做到不合适,而且更难以就地完成。在这里,您可以找到针对来自排列的就地重新排列的一些相关实现:In-place array reordering?

答案 1 :(得分:1)

每当我遇到这种类型的问题时,我会抓住一个qsort实现并修改它以接受 - 除了比较函数 - 一个额外的交换函数。

通过这种方式,您可以交换所有并行数据中的项目。

答案 2 :(得分:0)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct arrayset {
    int *values1;
    int *values2;
    int *values3;
};

void custom_sort(struct arrayset *v, size_t size);

int main() {
    struct arrayset work = {
        (int []){ 32, 10, 101, 72, 13, 5 },
        (int []){ 40, 10, 100, 90, 20, 2 },
        (int []){ 16, 14,  93,  2, 37, 39}
    };
    custom_sort(&work, 6);
    for(int i=0;i<6;++i){
        printf("%d, %d, %d\n",
            work.values1[i], work.values2[i], work.values3[i]);
    }
    return 0;
}

typedef struct pair {
    int key, value;
} Pair;

int cmp(const void *x, const void *y){
    int a = ((const Pair*)x)->key;
    int b = ((const Pair*)y)->key;
    return a < b ? -1 : a > b;
}

void custom_sort(struct arrayset *v, size_t size){
    Pair key[size];
    for(int i=0;i<size;++i){
        key[i].key  = v->values1[i];
        key[i].value=i;
    }
    qsort(key, size, sizeof(Pair), cmp);
    int v1[size], v2[size], v3[size];
    memcpy(v1, v->values1, size*sizeof(int));
    memcpy(v2, v->values2, size*sizeof(int));
    memcpy(v3, v->values3, size*sizeof(int));
    for(int i=0;i<size;++i){
        v->values1[i] = v1[key[i].value];
        v->values2[i] = v2[key[i].value];
        v->values3[i] = v3[key[i].value];
    }
}