【编程题】堆排序(java实现)

【编程题】堆排序(java实现)

思路
* 第一步:时间复杂度O(n);从数组0到n建立大根堆(对于第i个元素,左孩子为left=2i+1,右孩子right=2i+2=left+1,父节点为(i-1)/2);
* 第二步:n次将大根堆顶与堆的最后一个元素交换,将堆元素减一
* 第三步:时间复杂度O(logn);重新调整堆结构,将上一步交换后的堆顶元素下沉

package sort;

import java.util.Arrays;

public class HeapSort {
    public static void main(String[] args){
        int[] a={4,8,1,5,3,6};
        heapSort(a);
        System.out.println(Arrays.toString(a));
    }

    /**
     * 第一步:O(n)建立大根堆(对于第i个元素,左孩子为left=2*i+1,右孩子right=2*i+2=left+1,父节点为(i-1)/2);
     * 第二步:n次将大根堆顶与堆的最后一个元素交换,将堆元素减一
     * 第三步:O(logn)重新调整堆结构,将上一步交换后的堆顶元素下沉
     * @param arr
     */
    static void heapSort(int[] arr){
        if(arr==null||arr.length<2)
            return;
        for(int i=0,len=arr.length;i<len;i++)
            heapInsert(arr,i);
        int heapSize=arr.length;
        swap(arr,0,--heapSize);
        while (heapSize>0){
            heapify(arr,0,heapSize);
            swap(arr,0,--heapSize);
        }

    }

    /**
     * 建堆过程,如果当前新添加的节点元素比堆顶元素大,则和堆顶元素交换,依次往上比较
     * @param arr
     * @param index
     */
    static void heapInsert(int[] arr,int index){
            while (arr[index]>arr[(index-1)/2]){//当前元素为arr[index],父元素为arr[(index-1)/2]
                swap(arr,index,(index-1)/2);
                index=(index-1)/2;
            }

    }

    /**
     * 下沉过程,如果堆顶元素不是最大,则将堆顶元素与左右儿子的最大值交换,依次往下比较
     * @param arr
     * @param index
     * @param heapsize
     */
    static void heapify(int[] arr,int index,int heapsize){
        int left=2*index+1;//左儿子
        while (left<heapsize){
            int bigsize=left+1<heapsize&&arr[left]<arr[left+1]?left+1:left;//如果右儿子存在且右儿子比左儿子大,则最大值为右儿子,否则为左儿子
            bigsize=arr[bigsize]>arr[index]?bigsize:index;//判断堆顶元素和左右儿子的最大值比较,取最大值
            if(bigsize==index)//如果最大为当前的堆顶,退出
                break;
            swap(arr,bigsize,index);//否则,将当前部分堆的堆顶与最大交换
            index=bigsize;//当前节点往下比较
            left=2*index+1;
        }
    }
    static void swap(int[] arr,int i,int j){
        int tem=arr[i];
        arr[i]=arr[j];
        arr[j]=tem;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值