1. 程式人生 > >排序算法的c++實現——計數排序

排序算法的c++實現——計數排序

tar 可能 重要 for 比較 git 交換 email sizeof

任何比較排序算法的時間復雜度的上限為O(NlogN), 不存在比o(nlgN)更少的比較排序算法。如果想要在時間復雜度上超過O(NlogN)的時間復雜度,肯定需要加入其它條件。計數排序就加入了限制條件,從而使時間復雜度為O(N).

計數排序的核心思想(來自算法導論):計數排序要求待排序的n個元素的大小在[0, k]之間,並且k與n在一個數量級上,即k=O(n).對於每一個輸入元素x, 確定小於等於x的個數為i。利用這一信息,就可以把元素x放到輸出數組的正確位置,即把元素x放到輸出數組下標為i-1的位置。

重要說明:
1. 計數排序要求待排序的n個元素的大小在[0, k]之間,並且k與n在一個數量級上,即k=O(n).

此時使用計數排序可以把時間復雜度降到O(n)上。
2. 計數排序不是基於比較的排序算法,它基於計數策略。
3. 寫計數排序算法時,應該把它寫成穩定排序的。
4. 計數排序還是原址排序,它需要借助額外的內存空間。

代碼如下:

  1   /***********************************************************************
  2   *   Copyright (C) 2019  Yinheyi. <[email protected]>
  3   *   
  4   * This program is free software; you can redistribute it and/or modify it under the terms
5 * of the GNU General Public License as published by the Free Software Foundation; either 6 * version 2 of the License, or (at your option) any later version. 7 8 * Brief: 9 * Author: yinheyi 10 * Email: [email protected] 11 * Version: 1.0 12 * Created Time: 2019年05月11日 星期六 10時19分07秒
13 * Modifed Time: 2019年05月11日 星期六 14時00分09秒 14 * Blog: http://www.cnblogs.com/yinheyi 15 * Github: https://github.com/yinheyi 16 * 17 ***********************************************************************/ 18 #include<string.h> 19 #include<iostream> 20 21 // 任何比較排序算法的時間復雜度的上限為O(NlogN), 不存在比o(nlgN)更少的比較排序算法。 22 // 如果想要在時間復雜度上超過O(NlogN)的時間復雜度,肯定需要加入其它條件。計數排序就加入 23 // 了限制條件,從而使時間復雜度為O(N). 24 // 25 // 計數排序的核心思想(來自算法導論): 26 // 計數排序要求待排序的n個元素的大小在[0, k]之間,並且k與n在一個數量級上,即k=O(n). 27 // 對於每一個輸入元素x, 確定小於等於x的個數為i。利用這一信息,就可以把元素x放到輸出數組 28 // 的正確位置,即把元素x放到輸出數組下標為i-1的位置。 29 // 30 // 重要說明: 31 // 1. 計數排序要求待排序的n個元素的大小在[0, k]之間,並且k與n在一個數量級上,即k=O(n). 32 // 此時使用計數排序可以把時間復雜度降到O(n)上。 33 // 2. 計數排序不是基於比較的排序算法,它基於計數策略。 34 // 3. 寫計數排序算法時,應該把它寫成穩定排序的。 35 // 4. 計數排序還是原址排序,它需要借助額外的內存空間。 36 // 37 // 計數排序代碼如下: 38 // 參數說明:array表示數組指針,nLength_表示數組的最大長度,nMaxNumber_表示數組元素中的最大> 值; 39 void CountingSort(int array[], int nLength_, int nMaxNumber_) 40 { 41 // 參數的合法化檢測 42 if (nullptr == array || nLength_ <= 1 || nMaxNumber_ <= 0) 43 return; 44 45 // 統計待排序數組中每一個元素的個數 46 // 註意:此處new出來的數組的大小為nMaxNumber_ + 1, 用於統計[0, nMaxNumber_]範圍內的元素 47 int* ArrayCount = new int[nMaxNumber_ + 1]{0}; 48 for (int i = 0; i < nLength_; ++i) 49 { 50 ++ArrayCount[array[i]]; 51 } 52 53 // 此處計算待排序數組中小於等於第i個元素的個數. 54 // 備註:如果要進行大到小的排序,就計算大於等於第i個元素的個數, 也就從後向前進行累加; 55 for (int i = 1; i < nMaxNumber_ + 1; ++i) 56 { 57 ArrayCount[i] += ArrayCount[i-1]; 58 } 59 60 // 把待排序的數組放到輸出數組中, 為了保持排序的穩定性,從後向前添加元素 61 int* ArrayResult = new int[nLength_]; 62 for (int i = nLength_ - 1; i >=0; --i) 63 { 64 int _nIndex = ArrayCount[array[i]] - 1; // 元素array[i]在輸出數組中的下標 65 ArrayResult[_nIndex] = array[i]; 66 67 // 因為可能有重復的元素,所以要減1,為下一個重復的元素計算正確的下標; 68 --ArrayCount[array[i]]; 69 } 70 71 // 交換數據並釋放內存空間 72 memcpy(array, ArrayResult, sizeof(int) * nLength_); 73 delete [] ArrayCount; 74 ArrayCount = nullptr; 75 delete [] ArrayResult; 76 ArrayResult = nullptr; 77 } 78 79 // 測試代碼 80 /*************** main.c *********************/ 81 static void PrintArray(int array[], int nLength_); 82 int main(int argc, char* argv[]) 83 { 84 int test[10] = {12, 12, 4, 0, 8, 5, 2, 3, 9, 8}; 85 std::cout << "排序前:" << std::endl; 86 PrintArray(test, 10); 87 CountingSort(test, 10, 12); 88 std::cout << "排序後:" << std::endl; 89 PrintArray(test, 10); 90 91 return 0; 92 } 93 94 // 打印數組函數 95 static void PrintArray(int array[], int nLength_) 96 { 97 if (nullptr == array || nLength_ <= 0) 98 return; 99 100 for (int i = 0; i < nLength_; ++i) 101 { 102 std::cout << array[i] << " "; 103 } 104 105 std::cout << std::endl; 106 }

排序算法的c++實現——計數排序