堆排序Java算法

思路

堆排序分为三步:

  1. 首先写出如何从当前结点的树构造出最大堆的方法:max_Heap
  2. 然后把无序数组初始化成最大堆:build_Max_Heap
    此时该数组组成的完全二叉树已经符合最大堆的原则了,array[0]是最大值。

  3. 将第一个值和最后一个值交换,那么第一个最大的值就已经排在后面了,然后将堆长度减1。
    交换后该树就不符合最大堆原则了,此时调用max_Heap再构造出最大堆。
    然后再交换,把第二个最大值排在后面。
    交换length-1次,直到堆长度heap-size为1,便完成了排序。

    图解可以查看这个链接:图解链接

    代码

package com.internet.test;

import java.util.Arrays;

/**
 * 堆排序,时间复杂度为O(nlogN)
 *
 */

public class HeapSort {
    private static int[] array;
    private static int length;
    private static int heap_size;

    public static  void sort(int[] arr){
        array = arr;
        length = arr.length;
        heap_size = arr.length;
        build_Max_Heap(arr);
        swap_MaxIndex(arr);
    }


    //从index根节点开始构造出一个最大堆
    public static void max_Heap(int[] arr,int index){
        int largetIndex = index;
        //因为java是从0开始的,所以左孩子结点是index*2+1,右孩子结点是index*2+2
        int left = index*2+1;
        int right = index*2+2;
        //如果左孩子存在,则对比左孩子,选出最大值
        if(left<heap_size && arr[left] > arr[index]){
            largetIndex = left;
        }
        //如果右孩子存在,则对比右孩子,选出最大值
        if(right<heap_size && arr[right]>arr[largetIndex]){
            largetIndex = right;
        }

        //如果父结点已经最大,则无需交换了
        if(largetIndex != index){
            //不是最大则需要交换
            swap(index, largetIndex); 
            //交换之后的子树会破坏最大堆原则,所以对子树进行递归 
            max_Heap(arr, largetIndex); 
        }
    }

    //第一次从无序的数组构造出一个最大的堆
    public static void build_Max_Heap(int arr[]){
        //完全二叉树中最后一个拥有子结点的树的位置是length/2-1(数组从0开始,所以也要减1)
        //然后从最小树到最大树,不断构造出最大堆,直到整棵树为最大堆
        System.out.println("无序数组构造成最大堆的过程是:");
        for(int i=length/2-1;i>=0;i--){
            max_Heap(arr, i);
            System.out.println(Arrays.toString(arr));
        }

    }

    //将第一个值和最后一个值交换,然后堆长度减1,再构造出最大堆,然后再交换,交换length-1次,直到heap-size=1
    public static void  swap_MaxIndex(int arr[]) {
        for(int i=length;i>1;i--){
            swap(0, heap_size-1);
            heap_size--;
            max_Heap(arr, 0);

        }
    }

    //交换两个值
    public static void swap(int a,int b){
        int temp = array[a];
        array[a]=array[b];
        array[b]=temp;
    }

    public static void main(String[] args) {
        int[] array = {4,1,3,2,16,9,10,14,8,7};
        System.out.println("原数组为:\n"+Arrays.toString(array));
        HeapSort.sort(array);
        System.out.println("排序的结果是:");
        System.out.println(Arrays.toString(array));
    }
}

运行结果

原数组为:
[4, 1, 3, 2, 16, 9, 10, 14, 8, 7]
无序数组构造成最大堆的过程是:
[4, 1, 3, 2, 16, 9, 10, 14, 8, 7]
[4, 1, 3, 14, 16, 9, 10, 2, 8, 7]
[4, 1, 10, 14, 16, 9, 3, 2, 8, 7]
[4, 16, 10, 14, 7, 9, 3, 2, 8, 1]
[16, 14, 10, 8, 7, 9, 3, 2, 4, 1]
排序的结果是:
[1, 2, 3, 4, 7, 8, 9, 10, 14, 16]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值