目录
1、堆排序概述
指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
堆排序在代码的实现上是十分完美简洁的
原理:
1、堆初始化:创建一个大根堆。
2、元素下沉:将最后一个元素和第一个元素交换,再次下沉。每次下沉均可得到一个最大 元素放于尾部。
动画展示:
时间和空间复杂度:
堆排序的时间复杂度为:O(nlogn)
因为堆排序是就地排序,空间复杂度为常数:O(1)
2、堆排序分类
堆排序(原始版)、堆排序(递归版)
3、代码实现及运行结果
public static void main(String[] args) {
long starttime1=System.nanoTime();
System.out.println("堆排序(原始版)");
int[] nums1=new int[]{4,4,6,77,33,45,55,90,30,67,3,1,2,3,4,5,6,68,98,99,76,65,66,33,43,32,43};
sort(nums1);
long endtime1=System.nanoTime();//200ns
System.out.println("程序运行时间:"+(endtime1-starttime1)+"ns");
long starttime=System.nanoTime();
//*******************************
System.out.println("堆排序(递归版)");
int[] nums2=new int[]{4,4,6,77,33,45,55,90,30,67,3,1,2,3,4,5,6,68,98,99,76,65,66,33,43,32,43};
sort1(nums2);
for (int m = 0; m < nums2.length; m++) {
System.out.print(nums2[m]+",");
}
System.out.println();
long endtime=System.nanoTime();//200ns
System.out.println("程序运行时间:"+(endtime-starttime)+"ns");
}
/*public static void swap(int[] arr){
int temp=arr[0];
arr[0]=arr[1];
arr[1]=temp;
}*/
堆排序(原始版)
代码:
public static void heapify(int[]num,int start,int end){
int dad=start;//标记父节点
int son=2*dad+1;//标记子节点
while (son<=end){//交换值使得父节点值最大
if ((son +1<=end)&&(num[son]<num[son+1]))son++;
if(num[dad]>num[son])return;
/*int[] arr=new int[]{num[dad],num[son]};
swap(arr);
num[dad]=arr[0];
num[son]=arr[1];*/
int c=num[dad];
num[dad]=num[son];
num[son]=c;
dad=son;
son=2*dad+1;
}
}
public static void sort(int[] num){
//初始化大根堆
for (int i = (num.length-1)/2; i >=0 ; i--)heapify(num,i,num.length-1);
for (int m = 0; m < num.length; m++) {
System.out.print(num[m]+",");
}
System.out.println("初始化");
//首尾元素交换,首元素开始下沉,每次可得到最大值放于尾
for (int i = num.length-1; i >0 ; i--) {
/*int[] arr=new int[]{num[0],num[i]};
swap(arr);
num[i]=arr[1];
num[0]=arr[0];*/
int c=num[0];
num[0]=num[i];
num[i]=c;
heapify(num,0,i-1);
//打印查看
for (int m = 0; m < num.length; m++) {
System.out.print(num[m]+",");
}
System.out.println();
}
}
运行结果:
堆排序(原始版)
99,98,55,90,76,45,6,6,77,67,66,43,43,3,4,5,4,68,30,4,33,65,3,33,1,32,2,初始化
98,90,55,77,76,45,6,6,68,67,66,43,43,3,4,5,4,2,30,4,33,65,3,33,1,32,99,
90,77,55,68,76,45,6,6,32,67,66,43,43,3,4,5,4,2,30,4,33,65,3,33,1,98,99,
77,76,55,68,67,45,6,6,32,33,66,43,43,3,4,5,4,2,30,4,1,65,3,33,90,98,99,
76,68,55,33,67,45,6,6,32,33,66,43,43,3,4,5,4,2,30,4,1,65,3,77,90,98,99,
68,67,55,33,66,45,6,6,32,33,65,43,43,3,4,5,4,2,30,4,1,3,76,77,90,98,99,
67,66,55,33,65,45,6,6,32,33,3,43,43,3,4,5,4,2,30,4,1,68,76,77,90,98,99,
66,65,55,33,33,45,6,6,32,4,3,43,43,3,4,5,4,2,30,1,67,68,76,77,90,98,99,
65,33,55,32,33,45,6,6,30,4,3,43,43,3,4,5,4,2,1,66,67,68,76,77,90,98,99,
55,33,45,32,33,43,6,6,30,4,3,1,43,3,4,5,4,2,65,66,67,68,76,77,90,98,99,
45,33,43,32,33,43,6,6,30,4,3,1,2,3,4,5,4,55,65,66,67,68,76,77,90,98,99,
43,33,43,32,33,4,6,6,30,4,3,1,2,3,4,5,45,55,65,66,67,68,76,77,90,98,99,
43,33,6,32,33,4,5,6,30,4,3,1,2,3,4,43,45,55,65,66,67,68,76,77,90,98,99,
33,33,6,32,4,4,5,6,30,4,3,1,2,3,43,43,45,55,65,66,67,68,76,77,90,98,99,
33,32,6,30,4,4,5,6,3,4,3,1,2,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
32,30,6,6,4,4,5,2,3,4,3,1,33,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
30,6,6,3,4,4,5,2,1,4,3,32,33,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
6,4,6,3,4,4,5,2,1,3,30,32,33,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
6,4,5,3,4,4,3,2,1,6,30,32,33,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
5,4,4,3,4,1,3,2,6,6,30,32,33,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
4,4,4,3,2,1,3,5,6,6,30,32,33,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
4,3,4,3,2,1,4,5,6,6,30,32,33,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
4,3,1,3,2,4,4,5,6,6,30,32,33,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
3,3,1,2,4,4,4,5,6,6,30,32,33,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
3,2,1,3,4,4,4,5,6,6,30,32,33,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
2,1,3,3,4,4,4,5,6,6,30,32,33,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
1,2,3,3,4,4,4,5,6,6,30,32,33,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
程序运行时间:6315200ns
堆排序(递归版)
展示代码简洁,无注释。
代码:
public static void heapify1(int[]num,int start,int end){
int dad=start;//标记父节点
int son=2*dad+1;//标记子节点
if (son >end) return;
//交换值使得父节点值最大
if ((son +1<=end)&&(num[son]<num[son+1]))son++;
if(num[dad]>num[son])return;
//交换
int c=num[dad];
num[dad]=num[son];
num[son]=c;
heapify1(num,son,end);
}
public static void sort1(int[] num){
for (int i = (num.length-1)/2; i >=0 ; i--)heapify1(num,i,num.length-1);
for (int i = num.length-1; i >0 ; i--){
int c=num[0];
num[0]=num[i];
num[i]=c;
heapify1(num,0,i-1);
}
}
运行结果:
堆排序(递归版)
1,2,3,3,4,4,4,5,6,6,30,32,33,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
程序运行时间:297300ns
小 tip:
java中无引用传递,故以下代码不成立。(不能达到交换目的)
public static void swap(int a,int b){
int c=a;
a=b;
b=c;