堆排序(Java)
堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
- 时间复杂度:O(nlogn)
- 稳定性:不稳定
- 通过从最后一个非叶子结点开始比较,递归构建大(小)根堆,控制输出
图示
(图片来自:https://www.cnblogs.com/guoyaohua/p/8600214.html)
代码如下
public class Heapsort {
public static void main(String[] args) {
int arr[]= {3,7,2,4,6,8,5,9,0,1};
System.out.println("按升序排列后结果为:");
heapsort(arr);
}
public static void heapsort(int arr[]) {
for(int i=arr.length/2-1;i>=0;i--) {//构建生成大顶堆
adjustheap(arr,i,arr.length);
}
for(int j=arr.length-1;j>0;j--) {//将堆顶元素与末尾元素交换,将最大元素放到数组末端;
int temp=arr[j];
arr[j]=arr[0];
arr[0]=temp;
adjustheap(arr,0,j);
}
System.out.println(Arrays.toString(arr));
}
public static void adjustheap(int arr[],int i,int len) {//构建大顶堆
int temp=arr[i];
for(int j=i*2+1;j<len;j=j*2+1) {
if(j+1<len&&arr[j]<arr[j+1]) {
j++;
}
if(arr[j]>temp) {
arr[i]=arr[j];
i=j;
}else {
break;
}
}
arr[i]=temp;
}
}
运行结果
按升序排列后结果为:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
拓展
利用优先队列(PriorityQueue)控制输出,优先队列的作用是能保证每次取出的元素都是队列中权值最小的,通过完全二叉树实现的小顶堆,所以可以通过定义比较器控制输出。
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
//利用优先队列控制输出
//PriorQueue
public class Heapsort2 {
public static void main(String[] args) {
int arr[]= {3,7,2,4,6,8,5,9,0,1};
System.out.println("利用优先队列后的升序排序为:");
heapsort1(arr);
System.out.println("利用优先队列后的降序排序为:");
heapsort2(arr);
}
public static void heapsort1(int arr[]) {
PriorityQueue <Integer> q=new PriorityQueue<Integer>();//利用PriorityQueue:优先队列自身性质
for(int i:arr) {
q.offer(i);
}
while (!q.isEmpty()) {
System.out.print(q.poll() + " ");
}
System.out.println();
}
public static void heapsort2(int arr[]) {
Comparator<Integer> cmp = new Comparator<Integer>() { //比较器,可根据e2-e1:降序;e1-e2:升序,控制输出
public int compare(Integer e1, Integer e2) {
return e2 - e1;
}
};
Queue<Integer> q= new PriorityQueue<Integer>(cmp);//注意:此时定义优先队列要加入比较器
for(int i:arr) {
q.offer(i);
}
while (!q.isEmpty()) {
System.out.print(q.poll() + " ");
}
System.out.println();
}
}
运行结果
利用优先队列后的升序排序为:
0 1 2 3 4 5 6 7 8 9
利用优先队列后的降序排序为:
9 8 7 6 5 4 3 2 1 0