我目前正在研究一种算法,它要求我的多维数组(当前为3维)按第一项和第二项的和值进行排序。具体做法是:
(要交换的项目i和j的条件)
if ((Array[i][1]+Array[i][2]) > (Array[j][1]+Array[j][2])) return 1;
出于测试目的,我决定使用select sort。但是,我的算法需要在5秒内完成所有魔法。如果它有大约200 000个项目,则选择对自身进行排序需要大约10秒来对这样的数组进行排序。
我决定使用更好的算法,因为我对其余程序非常有信心。我知道unix系统包含一个内置的快速排序功能qsort(可通过终端中的 man qsort 获得)。但是,我不知道如何实现它。
我的想法是创建另一个数组,一维(1D),长度相同,包含主数组中项目的索引。通过这个,我可能只能排序辅助1D数组,其中第一项将具有最小总和的主数组中的项目索引,第二项将具有第二最小,依此类推。
但是,我该怎么办呢? Qsort函数需要提供比较函数,以决定是否交换。如果我确实创建了自己的比较函数(就像我在问题的开头所说的那样),当主要数组仅在 main 该函数,因此无法通过同一文件中的其他函数访问?
我会很高兴有任何提示或技巧如何解决这个问题。我也不热衷于使用qsort。如果您认为另一种排序算法可以做得更好,请告诉我。
非常感谢
答案 0 :(得分:1)
我只有有限的时间发布这个,但希望这个想法很明确。这是qsort可以设置的一种方式来做你正在寻找的东西。这是一个2D数组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