2017-03-08 55 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];