【问题标题】:C - Sort two arrays the same wayC - 以相同的方式对两个数组进行排序
【发布时间】:2016-01-02 02:10:41
【问题描述】:

所以我有两个数组(实际上是指针),我们称它们为 ab。我想首先对a 进行排序,然后保存我为获得该排序数组所做的确切交换并将它们应用于我的向量b。这是我的意思的一个简短示例:

int *a, *b;
//appropriate mallocs
a[0] = 2; a[1] = 3; a[2] = 1;
b[0] = 4; b[1] = 2; b[2] = 3;
//sort a in decreasing order --> a==[3, 2, 1]
//sort b based on sorting of a --> b==[2, 4, 3]

如何在不编写自己的排序函数的情况下实现这一点?

【问题讨论】:

  • 为此使用标准函数qsort
  • arrays (pointers actually)....闻起来很麻烦。
  • 您真的必须先对一个数组进行排序,然后再对另一个数组应用相同的转换,还是可以同时进行?
  • 你必须处理原始数据类型吗?保持数组中最后一个位置的结构怎么样?
  • 创建第三个数组 - a 的索引数组 - 最初用 0 .. countof(a) 填充。在 compare 函数中,使用索引比较 a 的元素。在qsort 完成后,第三个数组将包含元素的新顺序,您可以将其应用于ab

标签: c arrays sorting pointers


【解决方案1】:

这个例子做了原始问题所要求的,它以相同的方式对两个(或更多)数组进行排序,而不必将数组元素组合成一个公共结构。

它使用一个指针数组,所以比较函数不需要知道它正在排序的数组,只需要知道被排序元素的类型。可以修改为根据数组之一对多个数组进行排序。

它创建一个指向a[]的指针数组,使用qsort()根据a[]对指针数组进行排序,然后使用排序后的指针对a[]b[]重新排序(使用排序后的指针恢复到初始状态的副作用)。

重新排序的时间复杂度为 O(n),因为每个商店都将一个元素放在其排序位置。

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

int compare(const void *pp0, const void *pp1)
{
    int i0 = **(int **)pp0;
    int i1 = **(int **)pp1;
    if(i0 > i1)return -1;
    if(i0 < i1)return  1;
    return 0;
}

int main()
{
    int a[3] = {2, 3, 1};
    int b[3] = {4, 3, 2};
    int *pa[3];
    size_t i, j, k;
    int ta, 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 */
    qsort(pa, sizeof(a)/sizeof(a[0]), sizeof(pa[0]), compare);

    /* reorder a[] and b[] according to the array of pointers */
    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++)
        printf("%2d ", a[i]);
    printf("\n");

    for(i = 0; i < sizeof(a)/sizeof(a[0]); i++)
        printf("%2d ", b[i]);
    printf("\n");

    return 0;
}

【讨论】:

  • 优秀。删除了我的答案以突出显示您的答案。
  • +1 表示惊人的答案 -2 表示循环中的变量名。开个玩笑,这只是+1。变量名让我非常困惑。
  • @AdamZahran - 在 compare() 中,名称是 pp?表示它们是指向指针的指针。在 main 中,pa 表示指向 a 的指针,ta 和 tb 是 a[] 和 b[] 的临时值
【解决方案2】:

更好的解决方案是将数据分组到结构数组中,然后根据所需的键(即a 值)对其进行排序:

struct my_data {
  int a;
  int b;
};

struct my_data data[100];

static int data_cmp(const void *a, const void *b)
{
  const struct my_data *da = a, *db = b;

  return da->a < db->a ? -1 : da->a > db->a;
}

qsort(data, sizeof data / sizeof *data, sizeof *data, data_cmp);

这使用qsort() 进行排序,这通常是非常理想的。

【讨论】:

  • 不错,但如果您必须处理不同的数组,则不适用。
  • return da-&gt;a - db-&gt;a; 效率更高。
  • @ElderBug:是的,而且容易溢出。
  • @ElderBug 我从不使用它,如果存在数值溢出的风险,它的定义不明确。
  • @Amessihel 您可以将数据重新包装为结构数组,排序,然后展开。这可能会很昂贵,但也可能不会,并且使您不必为了提取交换而重新实现排序。
【解决方案3】:

这无法按要求解决,排序函数不会公开它们执行的交换。

但是,结果似乎可以通过结构来实现。

struct combined {
   int a_;
   int b_;
};

qsort 函数测试a_ 元素,同时也对b_ 数据进行排序。 同样,这需要一个比较函数

 int compare( const void * l, const void * r )
 {
     struct combined * _l= (struct combined *)l;
     struct combined * _r= (struct combined *)r;
     if( _l->a_ > _r->a_ ) return -1; // reverse sort
     if( _l->a_ < _r->a_ ) return 1;
     return 0;
 }

终于

 struct combined array[] = { {2,4}, {3,2}, {1,3} };
 qsort( array, 3, sizeof( struct combined), compare );

 array => { {3,2}, {2,4}, {1,3} };

【讨论】:

    【解决方案4】:
    // i am going to submit the idea not the code.
    
        int *a,*b;
        int *ord; // an array that holds indexes (sorting orders)
    
    //...
    
        a[ord[0]] = 2; a[ord[1]] = 3; a[ord[2]] = 1;
        b[ord[0]] = 4; b[ord[1]] = 2; b[ord[2]] = 3;
    
    //...
    //now you have just to sort the indexes array ord
    

    【讨论】:

      猜你喜欢
      • 2012-04-12
      • 2019-06-24
      • 1970-01-01
      • 2016-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多