【问题标题】:Qsorting a multidimensional array对多维数组进行 Qsorting
【发布时间】:2013-11-27 04:29:30
【问题描述】:

我目前正在研究一种算法,该算法要求我的多维数组(当前为 3 维)按第一项和第二项之和的值进行排序。具体来说:

(项目 i 和 j 交换的条件)

if ((Array[i][1]+Array[i][2]) > (Array[j][1]+Array[j][2])) return 1;

出于测试目的,我决定使用选择排序。但是,我的算法需要在 5 秒内完成所有魔法。如果它有大约 200 000 个项目,则选择排序本身需要大约 10 秒来对这样的数组进行排序。

我决定使用更好的算法,因为我对我的程序的其余部分非常有信心。我知道 unix 系统包含一个内置的快速排序功能 qsort(可通过终端中的 man qsort 获得)。但是,我不知道如何实现它。

我的想法是创建另一个数组,一维 (1D),长度相同,包含主数组中项目的索引。通过这一点,我可能只能对二级一维数组进行排序,其中第一项将在主数组中具有最小总和的项索引,第二项将具有第二小的项,依此类推。

但是,我该怎么做呢? Qsort函数需要提供比较函数,来决定是否交换。如果我确实创建了自己的比较函数(就像我在问题开始时所说的那样),当主数组仅在 main 函数,因此不能通过同一文件中的另一个函数访问?

我很乐意提供任何解决此问题的提示或技巧。我也不热衷于使用 qsort。如果您认为另一种排序算法可以做得更好,请告诉我。

非常感谢

【问题讨论】:

  • 为什么不将您的 3D 向量转换为 n*2 向量?正如您所解释的,smallVector[n][0] 是 3D 向量中的索引,而 smallVector[n][1] 是您需要排序的键。
  • 我不清楚你的确切要求你能发布你的 3D 数组的正式声明,一个 small 行数据样本(比如一个 3x3x3 样本,以及一个精确的对输出的期望(即您的比较器意识形态的逻辑以及您期望立方体在完成后的外观?(我很清楚,Array[0][]real“第一个”项目行, 用于计算吗?)
  • 我可以。如果您知道每个水箱的尺寸,则该程序的重​​点是用水填充空水箱。我在第一项中保存每个坦克的基地面积,在第二项中保存坦克的高度,在第三项中保存高度。我需要按高度对这些进行排序,每个坦克都在其中结束,即高度+高度,因此是 Array[i][1]+Array[i][2]。 P.S.:索引从 0 开始,所以第一个项目的索引是 0,第二个是 1 等等。
  • 好的。到目前为止,我只看到 2D。我相信如果这真的是 3D,我会在您更新的帖子中看到它。 qsort 应该能够为您执行此操作(至少根据我在您的描述中看到的内容,我认为是这样)。诀窍是让项目 width 正确,以便在 qsort 对数据进行洗牌时,项目 addresses 位于数组中的正确位置。
  • 你是对的。我没有意识到,这实际上只是二维数组。

标签: c arrays sorting multidimensional-array quicksort


【解决方案1】:

我只有有限的时间来发布这个,但希望这个想法很清楚。这是 qsort 可以设置为执行您要查找的操作的一种方式。这是一个二维数组 Nx3,我用 [0.0,500) 中的随机值填充了它。这个想法可以扩展到 3D 和超越阵列。

诀窍是让行宽正确(或者在 3D 平板、4D 立方体等的情况下......)

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

int cmp_row(const void* arg1, const void* arg2)
{
    const double *ar1 = arg1;
    const double *ar2 = arg2;

    double diff = (ar1[1] + ar1[2] - ar2[1] - ar2[2]);
    return (diff < 0.0) ? -1 : (0.0 < diff);
}

int main(int argc, char *argv[])
{
    static const int N = 50;
    double (*ar)[3] = NULL;
    int i=0;

    // see prng
    srand((unsigned)time(NULL));

    // allocat space for Nx3 2D array.
    ar = calloc(N, sizeof(*ar));

    // since I've no test data, random fill with values
    //  from [0..500)
    for (i=0;i<N;++i)
    {
        ar[i][1] = ((double)rand()/(double)RAND_MAX)*500.0;
        ar[i][2] = ((double)rand()/(double)RAND_MAX)*500.0;
    }

    // sort by elements 1+2
    qsort(ar, N, sizeof(*ar), cmp_row);

    for (i=0;i<N;++i)
    {
        printf("%3d : %7.3f + %7.3f  = %7.3f\n",
               i+1, ar[i][1], ar[i][2], ar[i][1]+ar[i][2]);
    }

    // release allocation
    free(ar);

    return 0;
}

注意:在处理我所说的纯语法 2D+ 数组时,这会变得有点复杂。这些将是我实际上是指针向量的“数组”。 int **ar 等。然而,前提几乎相同,只有比较器需要改变。如果我有时间,我会在输入允许的情况下添加这样一个野兽作为额外的样本。

最后注:这不能防止浮点值的潜在上溢或下溢。一个相当复杂的纯布尔逻辑比较器可以做到这一点,但除非你的数据对这种极端情况非常敏感,否则对于这个例子来说几乎不值得。

输出(显然你的会有所不同)

我已将ar[i][1] + ar[i][2] 的总和作为排序顺序的证据,我认为这是您想要的。我希望这会有所帮助。

  1 :  47.986 +   1.471  =  49.457
  2 : 114.418 +  26.848  = 141.267
  3 : 148.183 +  12.145  = 160.328
  4 :  46.925 + 161.231  = 208.155
  5 : 102.405 + 116.097  = 218.502
  6 :  58.676 + 172.490  = 231.167
  7 : 144.797 +  99.977  = 244.774
  8 :   8.914 + 314.920  = 323.833
  9 :  68.885 + 255.924  = 324.809
 10 : 107.825 + 220.631  = 328.457
 11 : 287.056 +  44.610  = 331.665
 12 : 217.505 + 114.799  = 332.304
 13 : 240.620 + 104.506  = 345.127
 14 : 242.288 + 133.509  = 375.797
 15 : 381.538 +   4.073  = 385.611
 16 :   4.991 + 383.519  = 388.510
 17 : 257.611 + 163.872  = 421.483
 18 :  43.278 + 380.951  = 424.230
 19 : 300.775 + 129.879  = 430.654
 20 : 134.814 + 314.688  = 449.502
 21 : 103.281 + 346.874  = 450.155
 22 : 197.761 + 263.668  = 461.429
 23 : 303.872 + 173.430  = 477.302
 24 : 466.265 +  11.400  = 477.665
 25 : 108.817 + 391.995  = 500.812
 26 : 467.992 +  40.985  = 508.977
 27 : 353.493 + 160.398  = 513.891
 28 : 406.446 + 130.214  = 536.659
 29 : 244.678 + 303.989  = 548.667
 30 : 303.282 + 260.434  = 563.716
 31 : 254.139 + 317.150  = 571.290
 32 : 368.311 + 203.118  = 571.429
 33 : 372.654 + 201.597  = 574.251
 34 : 143.985 + 454.796  = 598.781
 35 : 254.561 + 402.038  = 656.598
 36 : 309.922 + 363.872  = 673.795
 37 : 196.554 + 478.447  = 675.000
 38 : 493.585 + 185.749  = 679.334
 39 : 438.196 + 257.858  = 696.054
 40 : 347.198 + 360.908  = 708.107
 41 : 262.210 + 456.034  = 718.244
 42 : 389.174 + 339.315  = 728.489
 43 : 300.199 + 446.422  = 746.621
 44 : 344.346 + 427.167  = 771.513
 45 : 317.604 + 470.313  = 787.917
 46 : 312.785 + 475.855  = 788.640
 47 : 334.682 + 492.928  = 827.609
 48 : 399.056 + 430.449  = 829.505
 49 : 460.128 + 373.025  = 833.154
 50 : 419.137 + 440.745  = 859.882

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-13
    • 2012-06-10
    • 1970-01-01
    • 2011-10-23
    • 2014-02-25
    相关资源
    最近更新 更多