一、基本思想
二、代码
package com.ws.排序.堆排序;
import java.util.Arrays;
public class HeapSort {
public static void main(String[] args) {
//将数组进行升序排序
int arr[]={4,6,8,5,9};
duipai(arr);
}
//堆排序
public static void duipai(int arr[]){
int temp;
System.out.println("堆排序!");
// //分布完成
// tiaodadingdui(arr,1,arr.length);
// System.out.println("第一次"+ Arrays.toString(arr));// 4 9 8 5 6
//
// tiaodadingdui(arr,0,arr.length);
// System.out.println("第二次"+Arrays.toString(arr));//9 6 8 5 4
//①将无序调整成一个堆
for (int i=arr.length/2-1;i>=0;i--){//有子节点的树
tiaodadingdui(arr,i,arr.length);
}
//②堆顶元素沉到末尾 一直循环,得到有序
for (int j =arr.length-1;j>0;j--){
//交换
temp=arr[j];
arr[j]=arr[0];
arr[0]=temp;
//重新调整结构,堆
tiaodadingdui(arr,0,j);
}
System.out.println(Arrays.toString(arr));
}
//将一个数组(二叉树)调整为一个大顶堆
/**
*功能: 完成将以i为根节点的树调整成大顶堆
* 比如 i=1 [4 6 8 5 9] => [4,9,8,5,6]
* 从i=1到i=0 从下到上,从左到右
* @param arr 待调整的数组
* @param i 表示非叶子节点在数组中的索引
* @param length 对多少个数进行调整 逐渐减少
* 三个当中找最大,把最大的放到堆顶
*/
public static void tiaodadingdui(int arr[],int i,int length){
int temp=arr[i];//保存当前元素值
//开始调整
/**
* k=i*2+1是当前节点i的左子节点
* k=k*2+1是当前节点下一个节点的左子节点
*/
for (int k=i*2+1;k<length;k=k*2+1){
if (k+1<length && arr[k]<arr[k+1]){// 当前比较的是在个数限定范围之内 左子节点小于右子节点
k++;//k指向右子节点 大的数
}
if (arr[k]>temp){//大的数节点大于父节点
arr[i]=arr[k];//子节点上移父节点(覆盖)
i=k;//下一次循环比较 i的位置下沉
}else {
break;
}
}
//结束后 局部以i为顶的树是大顶堆
arr[i]=temp;//将原来的顶放到新位置
}
}
堆排序!
[4, 5, 6, 8, 9]
大数据测试:
package com.ws.排序.堆排序;
import java.text.SimpleDateFormat;
import java.util.Date;
public class HeapSorts {
public static void main(String[] args) {
//将数组进行升序排序
System.out.println("########大数据排序80000########");
int[] a=new int[80000];
for (int i=0;i<80000;i++){
a[i]=(int)(Math.random()*8000000);
}
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String data=format.format(date);
System.out.println("排序前时间="+data);
//排序
duipai(a);
Date date1=new Date();
String data2=format.format(date1);
System.out.println("排序后的时间="+data2);
}
//堆排序
public static void duipai(int arr[]){
int temp;
// //分布完成
// tiaodadingdui(arr,1,arr.length);
// System.out.println("第一次"+ Arrays.toString(arr));// 4 9 8 5 6
//
// tiaodadingdui(arr,0,arr.length);
// System.out.println("第二次"+Arrays.toString(arr));//9 6 8 5 4
//①将无序调整成一个堆
for (int i=arr.length/2-1;i>=0;i--){//有子节点的树
tiaodadingdui(arr,i,arr.length);
}
//②堆顶元素沉到末尾 一直循环,得到有序
for (int j =arr.length-1;j>0;j--){
//交换
temp=arr[j];
arr[j]=arr[0];
arr[0]=temp;
//重新调整结构,堆
tiaodadingdui(arr,0,j);
}
}
//将一个数组(二叉树)调整为一个大顶堆
/**
*功能: 完成将以i为根节点的树调整成大顶堆
* 比如 i=1 [4 6 8 5 9] => [4,9,8,5,6]
* 从i=1到i=0 从下到上,从左到右
* @param arr 待调整的数组
* @param i 表示非叶子节点在数组中的索引
* @param length 对多少个数进行调整 逐渐减少
* 三个当中找最大,把最大的放到堆顶
*/
public static void tiaodadingdui(int arr[],int i,int length){
int temp=arr[i];//保存当前元素值
//开始调整
/**
* k=i*2+1是当前节点i的左子节点
* k=k*2+1是当前节点下一个节点的左子节点
*/
for (int k=i*2+1;k<length;k=k*2+1){
if (k+1<length && arr[k]<arr[k+1]){// 当前比较的是在个数限定范围之内 左子节点小于右子节点
k++;//k指向右子节点 大的数
}
if (arr[k]>temp){//大的数节点大于父节点
arr[i]=arr[k];//子节点上移父节点(覆盖)
i=k;//下一次循环比较 i的位置下沉
}else {
break;
}
}
//结束后 局部以i为顶的树是大顶堆
arr[i]=temp;//将原来的顶放到新位置
}
}
########大数据排序80000########
排序前时间=2021-04-21 09:39:57
排序后的时间=2021-04-21 09:39:57