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

    任何比較排序算法的時間複雜度的上限爲O(NlogN), 不存在比o(nlgN)更少的比較排序算法。若是想要在時間複雜度上超過O(NlogN)的時間複雜度,確定須要加入其它條件。計數排序就加入了限制條件,從而使時間複雜度爲O(N).ios

    計數排序的核心思想(來自算法導論):計數排序要求待排序的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. 計數排序仍是原址排序,它須要藉助額外的內存空間。git

代碼以下: github

  1   /***********************************************************************
  2   *   Copyright (C) 2019  Yinheyi. <chinayinheyi@163.com>
  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: chinayinheyi@163.com
 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   }
相關文章
相關標籤/搜索