• Hark的数据结构与算法练习之计数排序


    算法说明

    计数排序属于线性排序,它的时间复杂度远远大于常用的比较排序。(计数是O(n),而比较排序不会超过O(nlog2nJ))。

    其实计数排序大部分很好理解的,唯一理解起来很蛋疼的是为了保证算法稳定性而做的数据累加,大家听我说说就知道了:

    1、首先,先取出要排序数组的最大值,假如我们的数组是int[] arrayData = { 2, 4, 1, 5, 6, 7, 4, 65, 42 };,那么最大值就是65.(代码17-21行就是在查找最大值)

    2、然后创建一个计数数组,计数数组的长度就是我们的待排序数组长度+1。即65+1=66。计数数组的作用就是用来存储待排序数组中,数字出现的频次。 例如,4出现了两次,那么计数数组arrayCount[4]=2。 OK,现在应该明白为什么计数数组长度为什么是66而不是65了吧? 因为为了存储0

        然后再创建一个存储返回结果的数组,数组长度与我们的原始数据长度是相同的。(24和26行)

    3、进行计数(代码29至31行)

    4、将计数数组进行数量累计,即arrayCount[i]+=arrayCount[i-1](代码35行至代码37行)。 

       目的是为了数据的稳定性, 这块我其实看了许久才看懂的…再次证明我的资质真的很差劲。 我来尽力解释一下:

         其实这个与后边那步结合着看理解起来应该更容易些。

         例如我们计数数组分别是 1 2 1 2 1 的话,那么就代表0出现了一次,1出现了两次,2出现了一次,3出现了两次。

      这个是很容易理解的。 那我们再换个角度来看这个问题。

      我们可以根据这个计数数组得到每个数字出现的索引位置,即数字0出现的位置是索引0,数字1出现的问题是索引1,2;数字2出现的位置是索引3,数字4出现的位置是索引4,5。。。。

      OK,大家可以看到,这个索引位置是累加的,所以我们需要arrayCount[i]+=arrayCount[i-1]来存储每个数字的索引最大值。 这样为了后边的输出

    5、最后,把原始数据从后往前输出;然后每个数字都能找到计数器的最后实现索引。  然后将数字存储在实际索引的结果数组中。 然后计数数组的索引--, 结果就出来了。

    PS:计数排序其实是特别吃内存的,所以应用场景是最大值确定并且不大,必须是正整数。 

    时间复杂度:

    O(n+k)  

    请对照下方代码:因为有n的循环,也有k的循环,所以时间复杂度是n+k

    空间复杂度:

    O(n+k)  

    请对照下方代码:需要一个k+1长度的计数数组,需要一个n长度的结果数组,所以空间复杂度是n+k

    代码

    使用的是java

    /*
     * 计数排序
     */
    public class CountingSort {
    	public static void main(String[] args) {
    		int[] arrayData = { 2, 3, 1, 5, 6, 7, 4, 65, 42 };
    		int[] arrayResult = CountintSort(arrayData);
    		for (int integer : arrayResult) {
    			System.out.print(integer);
    			System.out.print(" ");
    		}
    	}
    
    	public static int[] CountintSort(int[] arrayData) {
    		int maxNum = 0;
    		// 取出最大值
    		for (int i : arrayData) {
    			if (i > maxNum) {
    				maxNum = i;
    			}
    		}
    
    		// 计数数组
    		int[] arrayCount = new int[maxNum + 1];
    		// 结构数组
    		int[] arrayResult = new int[arrayData.length];
    
    		// 开始计数
    		for (int i : arrayData) {
    			arrayCount[i]++;
    		}
    
    		// 对于计数数组进行 i=i+(i-1)
    		// 目的是为了保证数据的稳定性
    		for (int i = 1; i < arrayCount.length; i++) {
    			arrayCount[i] = arrayCount[i] + arrayCount[i - 1];
    		}
    
    		for (int i = arrayData.length - 1; i >= 0; i--) {
    			arrayResult[arrayCount[arrayData[i]] - 1] = arrayData[i];
    			arrayCount[arrayData[i]]--;
    		}
    
    		return arrayResult;
    
    	}
    }
    

    结果

    1 2 3 4 5 6 7 42 65 
    

    参考:

    http://blog.csdn.net/sjin_1314/article/details/8655061

    http://www.cnblogs.com/eaglet/archive/2010/09/16/1828016.html

  • 相关阅读:
    b/s批量下载文件
    b/s批量下载图片
    python函数总结(转载的 有空看下)
    使用命令行执行需要传参的 py文件的方法
    Jmeter3.1官方自带的HTML图形测试报告 + 汉化 (Jmeter 3.1~5.0通用)(有空试一下)
    Jmeter 获取响应时间图形、TPS的三个插件(有空试一下)
    把表里面的字段连起来 输出到一个字段里面的方法 concat()
    testng要了解的
    包的相互调用的方法
    包目录展示方法设置,和 包里面建包的方法
  • 原文地址:https://www.cnblogs.com/hark0623/p/4349350.html
Copyright © 2020-2023  润新知