堆排序
概述
堆排序算法的时间复杂度为nlog2n,最坏最好情况下都是nlog2n,空间复杂度为o(1),是不稳定的排序算法。
完全二叉树介绍
通过下图映射关系,可以知道数组中元素索引和满二叉树具体位置的对应关系
构建最小堆
比较思路
比较顺序-不断和子节点进行比较
- 如果比子节点都小就停止
- 否则相互替换,继续和底部子节点比较,直到没有子节点
// parent*2+1 parent*2+2
public static void creatHeap(int[] array,int parent,int length){
int cur_parent=parent;
int cur_children=parent*2+1;
while (true){
if(cur_children>=length)break;
if(cur_children+1<length && array[cur_children+1]<array[cur_children]){
cur_children++;
}
if(array[cur_parent]<array[cur_children])return;
int temp=array[cur_parent];
array[cur_parent]=array[cur_children];
array[cur_children]=temp;
cur_parent=cur_children;
cur_children=cur_children*2+1;
}
}
遍历思路
逆序遍历,由堆的底部到上面进行,保证不会有比较的遗漏
public static void heapsort(int[] array){
for (int i = array.length/2; i >=0 ; i--) {
creatHeap(array,i,array.length);
}
System.out.println("整体构建最小堆,降序是建最小堆---------------------------------");
System.out.println(Arrays.toString(array));
printHead(array);
for (int i = array.length-1; i >=1 ; i--) {
int temp=array[i];
array[i]=array[0];
array[0]=temp;
creatHeap(array,0,i);
System.out.println("第"+(array.length-i)+"次调整堆---------------------------------");
System.out.println(Arrays.toString(array));
printHead(array);
}
}
测试
public static void main(String[] args) {
int []arr = {17,34,-4,111,8,7,6,2,8,11,1,5,9};
System.out.println("数据初始化---------------------------------");
System.out.println(Arrays.toString(arr));
printHead(arr);
heapsort(arr);
System.out.println(Arrays.toString(arr));
}
public static void printHead(int[] array){ //以树的形状输出数组
int cur=0;
int count=1;
for (int i = 0; i < count; i++) {
StringBuffer sb=new StringBuffer();
for (int j = 0; j < count; j++) {
if(cur>=array.length){
System.out.println(sb);
return;
}
sb.append(array[cur++]+" ");
}
System.out.println(sb);
count*=2;
}
}
整体代码
public class Main {
public static void main(String[] args) {
int []arr = {17,34,-4,111,8,7,6,2,8,11,1,5,9};
System.out.println("数据初始化---------------------------------");
System.out.println(Arrays.toString(arr));
printHead(arr);
heapsort(arr);
System.out.println(Arrays.toString(arr));
}
public static void printHead(int[] array){
int cur=0;
int count=1;
for (int i = 0; i < count; i++) {
StringBuffer sb=new StringBuffer();
for (int j = 0; j < count; j++) {
if(cur>=array.length){
System.out.println(sb);
return;
}
sb.append(array[cur++]+" ");
}
System.out.println(sb);
count*=2;
}
}
public static void heapsort(int[] array){
for (int i = array.length/2; i >=0 ; i--) {
creatHeap(array,i,array.length);
}
System.out.println("整体构建最小堆,降序是建最小堆---------------------------------");
System.out.println(Arrays.toString(array));
printHead(array);
for (int i = array.length-1; i >=1 ; i--) {
int temp=array[i];
array[i]=array[0];
array[0]=temp;
creatHeap(array,0,i);
System.out.println("第"+(array.length-i)+"次调整堆---------------------------------");
System.out.println(Arrays.toString(array));
printHead(array);
}
}
// parent*2+1 parent*2+2
public static void creatHeap(int[] array,int parent,int length){
int cur_parent=parent;
int cur_children=parent*2+1;
while (true){
if(cur_children>=length)break;
if(cur_children+1<length && array[cur_children+1]<array[cur_children]){
cur_children++;
}
if(array[cur_parent]<array[cur_children])return;
int temp=array[cur_parent];
array[cur_parent]=array[cur_children];
array[cur_children]=temp;
cur_parent=cur_children;
cur_children=cur_children*2+1;
}
}
}
输出结果
数据初始化---------------------------------
[17, 34, -4, 111, 8, 7, 6, 2, 8, 11, 1, 5, 9]
17
34 -4
111 8 7 6
2 8 11 1 5 9
整体构建最小堆,降序是建最小堆---------------------------------
[-4, 1, 5, 2, 8, 7, 6, 111, 8, 11, 34, 17, 9]
-4
1 5
2 8 7 6
111 8 11 34 17 9
第1次调整堆---------------------------------
[1, 2, 5, 8, 8, 7, 6, 111, 9, 11, 34, 17, -4]
1
2 5
8 8 7 6
111 9 11 34 17 -4
第2次调整堆---------------------------------
[2, 8, 5, 9, 8, 7, 6, 111, 17, 11, 34, 1, -4]
2
8 5
9 8 7 6
111 17 11 34 1 -4
第3次调整堆---------------------------------
[5, 8, 6, 9, 8, 7, 34, 111, 17, 11, 2, 1, -4]
5
8 6
9 8 7 34
111 17 11 2 1 -4
第4次调整堆---------------------------------
[6, 8, 7, 9, 8, 11, 34, 111, 17, 5, 2, 1, -4]
6
8 7
9 8 11 34
111 17 5 2 1 -4
第5次调整堆---------------------------------
[7, 8, 11, 9, 8, 17, 34, 111, 6, 5, 2, 1, -4]
7
8 11
9 8 17 34
111 6 5 2 1 -4
第6次调整堆---------------------------------
[8, 8, 11, 9, 111, 17, 34, 7, 6, 5, 2, 1, -4]
8
8 11
9 111 17 34
7 6 5 2 1 -4
第7次调整堆---------------------------------
[8, 9, 11, 34, 111, 17, 8, 7, 6, 5, 2, 1, -4]
8
9 11
34 111 17 8
7 6 5 2 1 -4
第8次调整堆---------------------------------
[9, 17, 11, 34, 111, 8, 8, 7, 6, 5, 2, 1, -4]
9
17 11
34 111 8 8
7 6 5 2 1 -4
第9次调整堆---------------------------------
[11, 17, 111, 34, 9, 8, 8, 7, 6, 5, 2, 1, -4]
11
17 111
34 9 8 8
7 6 5 2 1 -4
第10次调整堆---------------------------------
[17, 34, 111, 11, 9, 8, 8, 7, 6, 5, 2, 1, -4]
17
34 111
11 9 8 8
7 6 5 2 1 -4
第11次调整堆---------------------------------
[34, 111, 17, 11, 9, 8, 8, 7, 6, 5, 2, 1, -4]
34
111 17
11 9 8 8
7 6 5 2 1 -4
第12次调整堆---------------------------------
[111, 34, 17, 11, 9, 8, 8, 7, 6, 5, 2, 1, -4]
111
34 17
11 9 8 8
7 6 5 2 1 -4
[111, 34, 17, 11, 9, 8, 8, 7, 6, 5, 2, 1, -4]
Process finished with exit code 0