2017-03-08 54 views
1

我了解compare函数正在对值进行排序,以便显示按降序排列的数字组合。这个比较函数是如何工作的?

例如:给定[3, 30, 34, 5, 9],最大的成形数字是9534330

int compare(const void *a1,const void *b1){ 
     int a = *(int*)a1; 
     int b = *(int*)b1; 
     int i=0; 
     char arr[10000]={0}; 
     char brr[10000]={0}; 
     sprintf(arr, "%d%d", a, b); 
     sprintf(brr, "%d%d", b, a); 
     int k = strlen(arr); 
     for(i=0; i < k; i++){ 
      if(arr[i] != brr[i]) 
       return brr[i] - arr[i]; 
     } 
     return b-a; 
    } 
    char* largestNumber(const int* A, int n1) { 
     char *ans = (char*) calloc(10000000,sizeof(char)); 
     int i=0, count=0; 
     qsort(A, n1, sizeof(int), compare); 
     if(A[0] == 0){ 
      ans[0] = '0'; ans[1]=0; return ans; 
     } 
     for(i=0; i<n1; i++){ 
      int k = A[i]; 
      // printf("%d ", k); 
      count += sprintf(ans+count, "%d", k); 
     } 
     // printf("\n"); 
     ans[count] = 0; 
     return ans; 
    } 

我的疑惑是:

  1. 如何这段代码的工作?

    for(i=0; i < k; i++){ 
        if(arr[i] != brr[i]) 
         return brr[i] - arr[i]; 
    } 
    

    它比较arrbrr内容,但如何使这些值以这种方式得到分类将其返回值?

  2. 即使它返回值,它们应该按递增顺序打印。为什么它以降序显示它们?

+1

注意:1)可以使用int k = sprintf(arr,“%d%d”,a,b);'“sprintf函数返回写入数组的字符数,不包括结束的空字符如果发生编码错误,则为负值。“ 2)'char arr [10000] = {0};'相当极端,也许'char arr [100] = {0};'?3)整个for(i = 0; i chux

+0

如果您在提供给'qsort'的'compare'函数内使用'sprintf'和循环,则可能需要一整天和一天的时间。这个函数是为了简单地比较一个值,或者是在struct中有一个层次结构。但是你的“比较”函数似乎试图接管'qsort'的工作。也许你应该重新考虑算法。该解决方案可能会受益于递归方法。 –

+0

@WeatherVane不同意 - 它仍然是一个日志问题,'sprintf()'只是形成了要比较的词典值。 – chux

回答

0

这个比较函数很奇怪。
要了解它是如何工作的,让我们开始考虑what qsort expects:预计接受2号,ab功能,并

返回不到一个整数,等于或大于0,如果第一个参数分别被认为小于,等于或大于第二个参数。

在这种情况下,如我们所看到的,它实际上返回相反的结果,即,它返回一个小于整数,等于或大于0,如果第二参数被分别较少考虑比,等于或大于第一个。这只是因为此代码的作者想按降序排序而不是升序排序。

这就是说,这个比较函数是一个特殊的函数:让我们来看看它的功能。虽然它适用于数字(它接受void*,这是一个通用指针,但它将这两个参数都转换为int*并对它们进行解引用),但它不会以数字方式进行比较,即使采用经典的字母数字方式。 相反,它表明两个数字一旦转换为字符串后,将按照哪个顺序进行连接以生成数字序列,该数字序列被解释为数字,从而产生最大可能的结果(这由另一个数字的名称暗示)功能,largestNumber)。它通过表明最大的数字是必须先采取的数字。这听起来很复杂,但一些例子会澄清。

让我们以数字3和4,如果你把它们当做字符串("3""4"),你可以将它们连接在两个不同的订单,让无论是"34""43"。现在,将这些字符串转换回数字:哪一个更大?显然,如果你想要最大的数字(43),你必须以4为第一个数字,3为第二个数字。在这种情况下,函数会告诉你最大的数字是4.它通过返回一个正数(在这种情况下为1)来实现。

让我们来取代30和4。如果连接它们,您可以获得"304""430"。因为304 < 430,函数告诉你最大的数字是4.所以,从这个角度来看,4> 30,这与数字排序相反。

如果拿图3和30,两个可能的串连是"330""303",并且由于330> 303必须首先将采取3和功能告诉你3> 30再次,这是数字的相反分类。

如果你把30和30你有"3030""3030",是相同之间做出选择,在这种情况下,函数返回0。

现在一个棘手的情况:如果你比较3和33,这两个“串化”数字是相同的("333""333"),所以我们期望为0.实际上,在这种情况下,函数会告诉您最大的数字是第二个数字......但这并不重要,因为结果是相同。

这个比较是如何工作的?首先,使用sprintf将数字转换为字符串。考虑到2个字符串(我们称它们为"ab""ba")必须具有相同的长度,因此它会检查一个长度为strlen的长度,然后循环检查每个数字,从第一个开始。如果abba之间的数字相同,则它什么都不做,只是进入下一个;如果不同,则比较它们并返回brr的数字减去arr的数字。例如,当比较3和30时,arr将包含330和brr 303.在第一次迭代中(当i==0时)它将检查第一个数字:两者均为3,因此您无法选择哪个数字更高。移到第二个数字:3> 0,所以arr>brr,所以函数必须返回一个负数,并且确实如此:它返回0 - 3 = -3

所以,函数比较ab并返回:

  • 如果他们以这种顺序连接它们产量最大数的负数(A,B);
  • 0,如果数字相同,那么它们的顺序无关紧要;
  • 一个正数,如果他们必须以相反的顺序连接(b,a)以产生最大数量。

下表显示了经典的数字排序,经典的字母数字排序的结果,而这种自定义排序(我已经被称为“最大的字符串化的数字排序”)

a b Numeric sort Alphanumeric sort Largest stringified number sort 
3 4  3 < 4   3 < 4   34 < 43 --> return 1 > 0 --> 3 < 4 
30 4  30 > 4   30 < 4   304 < 430 --> return 1 > 0 --> 30 < 4 
3 30  3 < 30   3 < 30   330 > 303 --> return -3 < 0 --> 3 > 30 
3 31  3 < 31   3 < 31   331 > 313 --> return -2 < 0 --> 3 > 31 
3 32  3 < 32   3 < 32   332 > 323 --> return -1 < 0 --> 3 > 32 
3 33  3 < 33   3 < 33   333 == 333 --> return 30 > 0 --> 3 < 33 
3 34  3 < 34   3 < 34   334 < 343 --> return 1 > 0 --> 3 < 34 
30 30  30 == 30   30 == 30   3030 == 3030 --> return 0 == 0 --> 30 == 30 

至于为何他们打印在递减的顺序,它只是这一行的,因为:

return brr[i] - arr[i]; 

如果你想看到他们在递增顺序,将其更改为:

return arr[i] - brr[i];