zoukankan      html  css  js  c++  java
  • 排序算法的c++实现——计数排序

        任何比较排序算法的时间复杂度的上限为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. <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   }
  • 相关阅读:
    centos下tomcat自启动
    navcat12 windows 下载安装
    mysql8 windows 下载安装
    redis windows下载安装
    python json.dumps()函数输出json格式,使用indent参数对json数据格式化输出
    Python的安装图解
    spark入门系列教程二——简单入门实例
    Spark入门系列教程一 —— Spark2.3.1 集群安装
    css在文字两边加线,文字居中效果——实战应用
    a标签中对于邮箱和电话的用法mark
  • 原文地址:https://www.cnblogs.com/yinheyi/p/10849708.html
Copyright © 2011-2022 走看看