Java实现堆排序和计数排序
堆排序代码:
思想:每次都取堆顶的元素,将其放在序列最后面,然后将剩余的元素重新调整为最小堆,依次类推,最终得到排序的序列。
import java.util.Arrays; /**
* 思路:首先要知道大顶堆和小顶堆,数组就是一个堆,每个i节点的左右孩子是2i+1和2i+2
* 有了堆,将其堆化:从(n/2)-1个元素开始向下修复,将每个节点修复为小(大)顶堆
* 修复完成后,数组具有小(大)顶堆的性质
* 按序输出:小顶堆可以对数组逆序排序,每次交换堆顶和末尾元素,对堆顶进行向下修复,这样次小元素又到堆顶了
*
* 时间复杂度:堆化:一半的元素修复,修复是单分支的,所以整体堆化为nlgn/2
* 排序:n个元素都要取出,因此调整n次,每次调整修复同上是lgn的,整体为nlgn
* 空间复杂度:不需要开辟辅助空间
* 原址排序
* 稳定性
*
*/
public class HeapSort { static void sort(int []A){
// 堆排序第一步: 先对A进行堆化
makeMinHeap(A);
for(int x = A.length-1;x>=0;x--){
// 堆排序第二步: 把堆顶,0号元素和最后一个元素对调
swap(A, 0, x);
// 堆排序第三步:缩小堆的范围,对堆顶元素进行向下调整
MinHeapFixDown(A, 0, x);
}
} static void makeMinHeap(int[] A){
int n = A.length;
for(int i = n/2-1;i>=0;i--){
MinHeapFixDown(A,i,n);
}
} private static void MinHeapFixDown(int[] A, int i, int n) {
// 找到左右孩子
int left = 2 * i + 1;
int right = 2 * i + 2 ;
// 左孩子已经越界,i就是叶子节点
if (left>=n) {
return ;
}
// min 指向了左右孩子中较小的那个
int min = left;
if (right>=n) {
min = left;
}else {
if (A[right]<A[left]) {
min = right;
}
}
// 如果A[i]比两个孩子都要小,不用调整
if (A[i]<=A[min]) {
return ;
}
// 否则,找到两个孩子中较小的,和i交换
int temp = A[i];
A[i] = A[min];
A[min] = temp;
// 小孩子那个位置的值发生了变化,i变更为小孩子那个位置,递归调整
MinHeapFixDown(A, min, n);
} private static void swap(int[] A, int p, int bigger) {
int temp = A[p];
A[p] = A[bigger];
A[bigger] = temp; } public static void main(String[] args) {
int arr[] = new int[10];
for(int i=0;i<10;i++){
arr[i] = (int) ((Math.random()+1)*10);
} System.out.println("排序前:"+Arrays.toString(arr));
sort(arr);
System.out.println("排序后:"+Arrays.toString(arr));
} }
堆排序结果:

计数排序代码:
import java.util.Arrays; /**
* 计数排序
* 思路:开辟新的空间,空间大小为max(source)+1
* 扫描source,将value作为辅助空间的下标,用辅助空间的该位置元素记录value的个数
* 如 9 7 5 3 1,helper的空间就为10
* 依次扫描,value为9,将helper[9]++,以此类推,完成之后,再去遍历helper
* 如果该位(index)的值为0,说明index不曾在source中出现
* 如果该位(index)的值为 1,说明出现了1次,为2说明出现了两次
* 时间复杂度:扫描一次source,扫描一次helper,复杂度为N+K
* 空间复杂度:如果source里面有个元素较大的,那么开辟的辅助空间较大
* 非原址排序
* 稳定性:相同元素不会出现交叉,非原址都是拷来拷去
* 如果要优化一下空间,可以求出minOf(source),那么helper的长度为(max-min)+1,这样就能短点
* 计数有缺陷,数据较为密集或范围较小时,适用。
*/
public class CountSort { static void sort(int []source){
int max = source[0];
for (int i = 1; i < source.length; i++) {
if (source[i]>max) {
max = source[i];
}
}
int []helper = new int[max+1];
for(int e:source){
helper[e]++;
}
int current = 0; // 数据回填的位置
for (int i = 1; i < helper.length; i++) {
while(helper[i]>0){
source[current++] = i;
helper[i]--;
}
}
} // 保证排序稳定性的版本
public static void sort2(int[] source) {
int max = source[0];
for (int i = 1; i < source.length; i++) {
if (source[i]>max) {
max = source[i];
}
}
int []helper = new int[max+1];
for (int e : source) {
helper[e]++;
}
for (int i = 1; i < helper.length; i++) {
helper[i] += helper[i - 1];
}
int len = source.length;
int[] target = new int[len];
for (int i = len - 1; i >= 0; i--) {
target[helper[source[i]] - 1] = source[i];
helper[source[i]]--;
}
System.arraycopy(target, 0, source, 0, len);
} public static void main(String[] args) {
int arr[] = new int[10];
for(int i=0;i<10;i++){
arr[i] = (int) ((Math.random()+1)*10);
}
System.out.println("排序前:"+Arrays.toString(arr));
sort2(arr);
System.out.println("排序后:"+Arrays.toString(arr));
} }
计数排序结果:

Java实现堆排序和计数排序的更多相关文章
- 排序算法<No.1> 【计数排序】
继上篇博文,今天我将先介绍一下什么是计数排序,将计数排序描述清楚后,再进行后续的桶排序方法解决这个问题. 通常情况下,一提到排序,大家第一反应就是比较,其实,今天我要说的这个计数排序,不是基于比较的排 ...
- 排序基础之非比较的计数排序、桶排序、基数排序(Java实现)
转载请注明原文地址: http://www.cnblogs.com/ygj0930/p/6639353.html 比较和非比较排序 快速排序.归并排序.堆排序.冒泡排序等比较排序,每个数都必须和其他 ...
- 计数排序和桶排序(Java实现)
目录 比较和非比较的区别 计数排序 计数排序适用数据范围 过程分析 桶排序 网络流传桶排序算法勘误 桶排序适用数据范围 过程分析 比较和非比较的区别 常见的快速排序.归并排序.堆排序.冒泡排序等属于比 ...
- 计数排序详解以及java实现
前言 我们知道,通过比较两个数大小来进行排序的算法(比如插入排序,合并排序,以及上文提到的快速排序等)的时间复杂度至少是Θ(nlgn),这是因为比较排序对应的决策树的高度至少是Θ(nlgn),所以排序 ...
- 八大排序方法汇总(选择排序,插入排序-简单插入排序、shell排序,交换排序-冒泡排序、快速排序、堆排序,归并排序,计数排序)
2013-08-22 14:55:33 八大排序方法汇总(选择排序-简单选择排序.堆排序,插入排序-简单插入排序.shell排序,交换排序-冒泡排序.快速排序,归并排序,计数排序). 插入排序还可以和 ...
- 算法-java代码实现计数排序
计数排序 第10节 计数排序练习题 对于一个int数组,请编写一个计数排序算法,对数组元素排序. 给定一个int数组A及数组的大小n,请返回排序后的数组. 测试样例: [1,2,3,5,2,3], ...
- 桶排序和计数排序的理解实现和比较(Java)
比较和非比较的区别 常见的快速排序.归并排序.堆排序.冒泡排序等属于比较排序.在排序的最终结果里,元素之间的次序依赖于它们之间的比较.每个数都必须和其他数进行比较,才能确定自己的位置.比较排序的优势是 ...
- 排序算法-计数排序(Java)
package com.rao.sort; import java.util.Arrays; /** * @author Srao * @className CountSort * @date 201 ...
- Java排序之计数排序
Java排序之计数排序 计数排序思路 计数排序适用于有明确范围的数组,比如给定一个数组,且知道所有值得范围是[m,n].这个时候可以使用一个n-m+1长度的数组,待排序的数组就可以散在这个数组上,数组 ...
随机推荐
- layUI 实现自定义弹窗
需求描述:点击表格中的数据,弹出一张具体信息表.描述的不是很清楚,放效果图,就明白了,上图 放心,能看到的数据,都不是生产数据,我造的假数据,但是功能效果就是这样,点击列表中的一行,弹出某些要展示的信 ...
- linux 笔记整理
1.常使用的进程管理命令 ps 显示显示主动的进程 . top 显示所用运行的进程 . 关闭进程 kill [pro Number ] . 关闭名为H的所有进程 killa ...
- OpenCV-Python:K值聚类
关于K聚类,我曾经在一篇博客中提到过,这里简单的做个回顾. KMeans的步骤以及其他的聚类算法 K-均值是因为它可以发现k个不同的簇,且每个簇的中心采用簇中所含值的均值计算 其他聚类算法:二分K-均 ...
- CF1065F Up and Down the Tree
题解: 和正解方法不太一样 正解的大概意思就是先向下走可以走回来的 再走不能走回来的 能走回来的就是到这个儿子后最近的叶子可以返回的 然后这样可以O(n)计算 我自己做的时候以为这样不太能做.. 所以 ...
- php八种常用函数
八种常用的数学函数: ① abs(x):求绝对值 ② ceil(x),floor(x):向上/下取最接近的整数 ③ cos(x),sin(x),tan(x):三角函数 ④ min(),max( ...
- PostgreSQL>窗口函数的用法
PostgreSQL之窗口函数的用法 转载请注明出处:https://www.cnblogs.com/funnyzpc/p/9311281.html PostgreSQL的高级特性本准备三篇的(递归. ...
- CentOS修改yum源
在安装完CentOS后一般需要修改yum源,才能够在安装更新rpm包时获得比较理想的速度.国内比较快的有163源.sohu源.这里以163源为例子. 1. cd /etc/yum.repos.d 2. ...
- python3 实现对代码文件中注释的翻译
心血来潮,昨天看见群里讨论一段图片转pdf的代码,直接拿过来发现不能用,原来是因为代码中传的文件对象不对,源码中说传递的是一个文件路径或一个文件对象.他传的是一个文件名,很是尴尬. 想了想,主要原因还 ...
- 在IDEA中spring程序可以正常运行,但IDE报错Could not autowire.
这个问题只会在使用xml文件配置bean时遇到,使用自动配置和java配置没有这种错误. 遇到这个问题首先要确定配置文件已经正确的放在了resources文件夹内,resources文件夹就是clas ...
- TypeScript 函数-函数类型
//指定参数类型 function add(x:number,y:number){ console.log("x:"+x); // reutrn(x+y); } //指定函数类型 ...