堆排序

224 阅读4分钟

堆排序

概述

堆排序算法的时间复杂度为nlog2n,最坏最好情况下都是nlog2n,空间复杂度为o(1),是不稳定的排序算法。

完全二叉树介绍

通过下图映射关系,可以知道数组中元素索引和满二叉树具体位置的对应关系

image.png

构建最小堆

比较思路

比较顺序-不断和子节点进行比较

  1. 如果比子节点都小就停止
  2. 否则相互替换,继续和底部子节点比较,直到没有子节点
    // 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 91次调整堆---------------------------------
[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 -42次调整堆---------------------------------
[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 -43次调整堆---------------------------------
[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 -44次调整堆---------------------------------
[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 -45次调整堆---------------------------------
[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 -46次调整堆---------------------------------
[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 -47次调整堆---------------------------------
[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 -48次调整堆---------------------------------
[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 -49次调整堆---------------------------------
[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 -410次调整堆---------------------------------
[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 -411次调整堆---------------------------------
[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 -412次调整堆---------------------------------
[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