排序算法<No.1> 【计数排序】
继上篇博文,今天我将先介绍一下什么是计数排序,将计数排序描述清楚后,再进行后续的桶排序方法解决这个问题。
通常情况下,一提到排序,大家第一反应就是比较,其实,今天我要说的这个计数排序,不是基于比较的排序算法。
计数排序的主要思路(精髓):
针对给定的一组整数数据,在其中任意选取一个数X,统计出这组数中不比X大的所有数据的个数n,那么,此时,X的大小次序就应该在这组数的n+1的位置了。
针对这个思想,有几点要注意:
1. 给定的数组A的数据,必须都是整数
2. 给定的数据比较稀疏的情况下,效率(空间)比较差
计数排序的处理逻辑,分为下面几步:
1. 找出输入数组A中的最小值min,以及最大值max,求出数组A的元素最大距离k = max - min + 1;
2. 初始化计数数组C,其数组长度为K;
3. 统计数组A中每个元素A[i]与最小值min的差值作为C数组的下标对应的元素的个数;
4. 计算出C数组中每个元素C[j]及其之前所有元素的和作为当前元素C[j]的新值;
5. 初始化输出数组B,其长度和输入数组A的长度一样;
6. 对数组A进行倒序的方式,将数组A的元素基于其元素的个数排位,进行对输出数组赋值,其中,考虑输入元素中有重复元素的情况;
理论比较的晦涩吧,那么先上代码吧,下面是JAVA代码实现的计数排序:
/**
* @author "shihuc"
* @date 2017年1月16日
*/
package jishuSort; import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.Scanner; /**
* @author chengsh05
*
*/
class InnerMaxMin {
int max;
int min;
/**
* @return the max
*/
public int getMax() {
return max;
}
/**
* @param max the max to set
*/
public void setMax(int max) {
this.max = max;
}
/**
* @return the min
*/
public int getMin() {
return min;
}
/**
* @param min the min to set
*/
public void setMin(int min) {
this.min = min;
}
}
public class CountSortDemo { /**
* @param args
*/
public static void main(String[] args) {
File file = new File("./src/jishuSort/sampleCount.txt");
Scanner sc = null;
try {
sc = new Scanner(file);
int N = sc.nextInt();
for(int i=; i<N; i++){
int S = sc.nextInt();
int A[] = new int[S];
for(int j=; j<S; j++){
A[j] = sc.nextInt();
}
int B[] = countSortResult(A);
printResult(B);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if(sc != null){
sc.close();
}
}
} /**
* 在时间复杂度为O(n)情况下,计算出最大值与最小值
*
* @param da
* @return
*/
public static InnerMaxMin getMaxMin(int da[]){
InnerMaxMin mm = new InnerMaxMin();
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for(int i=; i<da.length; i++){
if(da[i] > max){
max = da[i];
}
if(da[i] < min){
min = da[i];
}
} mm.setMax(max);
mm.setMin(min);
return mm;
} /**
* 获取最大值与最小值之间的距离 k
* 计算逻辑步骤1
*
* @param mm
* @return k
*/
public static int getDistance(InnerMaxMin mm){
return mm.getMax() - mm.getMin() + ;
} /**
* 获取转换后的计数数组C,然后将转换后的计数数组C进行计数。 此步骤的好处,是可以减少计数数组的空间开销,掐头和掐尾。
*
*
* @param A 原数组
* @param mm 最大最小值对象
* @return 差值数组
*/
public static int[] getCountArray(int A[], InnerMaxMin mm){
int K = getDistance(mm);
int min = mm.getMin(); /*
* 初始化计数数组C。
* 计算逻辑步骤2
*/
int C[] = new int[K];
Arrays.fill(C, ); /*
* 计算出每个输入数组A中的元素自生的个数,主要考虑的是有重复的情况,所以先单独计算出每个元素自己一共出现了多少次。
* 计算逻辑步骤3
*/
for(int i=; i<A.length; i++){
int n = A[i];
C[n - min]++;
} /*
* 用到了最简单的动态规划思路,统计原始输入数组A中比X元素小的所有元素的个数之和
* 计算逻辑步骤4
*/
for(int j=; j<C.length; j++){
C[j] = C[j] + C[j - ];
} return C;
} /**
* 计数排序的总入口函数
*
* @param A
* @return
*/
public static int[] countSortResult(int A[]){
/*
* 初始化计数数组的输出数组B。
* 计算逻辑步骤5
*/
int B[] = new int[A.length];
InnerMaxMin mm = getMaxMin(A);
int C[] = getCountArray(A, mm);
int min = mm.getMin(); /*
* 将输入元素基于其每个元素对应的计数个数排序操作,映射到相应的输出数组B的位置上。
* (对于输入数组元素中不比X元素大的元素的个数为n,那么X在排序后的输出数组中的位置为n+1)
* 计算逻辑步骤6
*/
for(int i = A.length - ; i>=; i--){
B[C[A[i] - min] - ] = A[i];
C[A[i] - min]--;
}
return B;
} /**
* 显示最终排序后的结果
*
* @param B
*/
public static void printResult(int B[]){
for(int i=; i<B.length; i++){
System.out.print(B[i] + " ");
}
System.out.println();
} }
下面也附带上我的测试数据:
也附带上测试后的结果:
这个算法,是稳定的算法,性能往往比常规的比较排序要好,但是使用场景也是受限的,即参与排序的元素必须是整数,且最好不要是稀疏数组。另外,计数排序的空间消耗,相比比较排序要高。 理解计数排序的核心思想中的计算的精髓,那么这个算法就理解了。结合代码,进行理解,还是不那么难的。
排序算法<No.1> 【计数排序】的更多相关文章
- 排序算法六:计数排序(Counting sort)
前面介绍的几种排序算法,都是基于不同位置的元素比较,算法平均时间复杂度理论最好值是θ(nlgn). 今天介绍一种新的排序算法,计数排序(Counting sort),计数排序是一个非基于比较的线性时间 ...
- 算法笔记_129:计数排序(Java)
目录 1 问题描述 2 解决方案 2.1比较计数排序 2.2 分布计数排序 1 问题描述 给定一组数据,请使用计数排序,得到这组数据从小到大的排序序列. 2 解决方案 2.1比较计数排序 下面算法 ...
- Java常见排序算法之直接选择排序
在学习算法的过程中,我们难免会接触很多和排序相关的算法.总而言之,对于任何编程人员来说,基本的排序算法是必须要掌握的. 从今天开始,我们将要进行基本的排序算法的讲解.Are you ready?Let ...
- Java排序算法之直接选择排序
Java排序算法之直接选择排序 基本过程:假设一序列为R[0]~R[n-1],第一次用R[0]和R[1]~R[n-1]相比较,若小于R[0],则交换至R[0]位置上.第二次从R[1]~R[n-1]中选 ...
- Hark的数据结构与算法练习之计数排序
算法说明 计数排序属于线性排序,它的时间复杂度远远大于常用的比较排序.(计数是O(n),而比较排序不会超过O(nlog2nJ)). 其实计数排序大部分很好理解的,唯一理解起来很蛋疼的是为了保证算法稳定 ...
- 《算法导论》——计数排序Counting Sort
今天贴出的算法是计数排序Counting Sort.在经过一番挣扎之前,我很纠结,今天这个算法在一些scenarios,并不是最优的算法.最坏情况和最好情况下,时间复杂度差距很大. 代码Countin ...
- 数据结构与算法-排序(八)计数排序(Counting Sort)
摘要 计数排序本质就是统计不同元素出现的次数,然后将元素依次从小到大放置,每个元素看统计的次数,就紧挨着放置几个同样的元素. 看似简单的处理,在算法中,会依据统计的元素次数推算出每个元素的索引位置,这 ...
- Python线性时间排序——桶排序、基数排序与计数排序
1. 桶排序 1.1 范围为1-M的桶排序 如果有一个数组A,包含N个整数,值从1到M,我们可以得到一种非常快速的排序,桶排序(bucket sort).留置一个数组S,里面含有M个桶,初始化为0.然 ...
- 第2章 排序 | 第10节 计数排序练习题 && 基数排序
对于一个int数组,请编写一个计数排序算法,对数组元素排序. 给定一个int数组A及数组的大小n,请返回排序后的数组. 测试样例: [1,2,3,5,2,3],6 [1,2,2,3,3,5] 计数排序 ...
- 八大排序算法之二希尔排序(Shell Sort)
希尔排序是1959 年由D.L.Shell 提出来的,相对直接排序有较大的改进.希尔排序又叫缩小增量排序 基本思想: 先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录 ...
随机推荐
- python day16--面向对象(01)
一.概念 类:具有相同属性的一类事物 比如人类是类,人类中的某个人是对象.食物是一类,米饭是一个对象 class Person: '''类体:两部分:变量部分,方法(函数)部分''' mind = ' ...
- 四条命令快速在Ubuntu16.04上配置DNS服务器
1. apt install dnsmasq -y 2. vim /etc/dnsmasq.d/resolv.conf address=/xxx.yyy.com/21.xx.xx.x 3. servi ...
- [转]自然语言处理中的Attention Model:是什么及为什么
自然语言处理中的Attention Model:是什么及为什么 https://blog.csdn.net/malefactor/article/details/50550211 /* 版权声明:可以 ...
- 对Dom的认识
一.相关的定义 1.文档对象模型(Document Object Model,简称DOM) 2.DOM可以以一种独立于平台和语言的方式访问和修改一个文档的内容和结构.换句话说,这是表示和处理一个HTM ...
- 一个简单的 IDA f5插件问题分析
有人提出问题,以下汇编f5结果缺失代码: .text:00000C18 Java_com_a_b_c .text:00000C18 PUSH {R3,LR} .text:00000C1A CMP R2 ...
- skflow 分类与回归接口API 简单测试
skflow也即是 tf.contrib.learn, 是 TensorFlow 官方提供的另外一个对 TensorFlow 的高层封装,通过这个封装,用户可以和使用 sklearn 类似的方法使用 ...
- 数据类型int、float、str、list、dict、set定义及常用方法汇总
数据类型int:记录整数事物状态 可变不可变:值不可变类型,改变变量值实则是改变了变量的指向 int():功能:1.工厂函数, i = 5 <==> i = int(5) 2.强制类型转换 ...
- Python的函数基础
引子 现在老板让你写一个监控程序,24小时全年无休的监控你们公司网站服务器的系统状况,当cpu\memory\disk等指标的使用量超过阀值时即发邮件报警,你掏空了所有的知识量,写出了以下代码 whi ...
- hdu4292 Food 最大流
You, a part-time dining service worker in your college’s dining hall, are now confused with a new pr ...
- [原]android 链接错误
由于没有使用NDK的makefile, 而是把NDK的toolchain集成到现有的build system, 所以出现了诡异的错误: unsupported dynamic reloc R_ARM_ ...