排序算法-选择排序之堆排序

来源:互联网 发布:榕基软件 编辑:程序博客网 时间:2024/06/05 22:50

堆是一种除了底层节点外的完全填满的二叉树,底层可以不完全,左到右填充。堆在实现优先队列的时候很有用。堆又分为大根堆和小根堆。大根堆的父节点的值大于等于两个子节点的值。小根堆的父节点的值小于等于两个子节点的值。
堆排序的思想是:每次从堆中取出最小(大)值,将取出的元素按顺序排到数组中,这样所有的元素就是从小到大(从大到小)排列在数组中。我们可以把删除最小值得到的元素重新排在一个数组中,或者排在该数组的末尾,减少空间。对堆的操作不是很难,插入就是将元素进行上滤。删除最小值相当于把树根置为空穴,将这个空穴下滤,下滤通过,两个子节点中最小的元素和空穴进行交换位置,下滤到最下面一层时,将数组末尾的元素放到空穴,保证每层是从左到右插入数据,最后将该元素上滤,保证父元素比两个子元素大。

代码

package com.creat.sort;import org.junit.Test;/** * Created by whz on 2017/8/23. */public class HeapSort {    @Test    public void test(){        Integer[] array = new Integer[]{10,54,55,47,50,20,41,33,40,28,70};        Integer[] newArray = new Integer[array.length+1];        buildHeap(array,newArray);        sort(newArray,array);        for(int i = 0; i < array.length; i++){            System.out.print(array[i]+" ");        }        System.out.println();    }    //排序    public static <T extends Comparable<? super T>> void sort(T[] array,T[] newArray){        int length = array.length;        for(int i = 0; i < newArray.length; i++){            newArray[i] = deleteMin(array,newArray.length -i );        }    }    //构建小根堆    public static <T extends Comparable<? super T>> void buildHeap(T[] array,T[] newArray){        newArray[0] = null;        for(int i = 1; i <= array.length; i++){            insert(newArray,array[i-1],i);        }    }    //删除最小值    private static <T extends Comparable<? super T>> T deleteMin(T[] array,int size){        T result = array[1];        array[1] = null;        int index = 1;        while(index*2 < array.length-1 && array[index*2] != null ){            if(array[index*2+1] == null || array[index*2].compareTo(array[index*2+1]) < 0){                array[index] = array[index*2];                index *= 2;            }else{                array[index] = array[index*2+1];                index = index*2+1;            }        }        insert(array,array[size],index);        array[size] = null;        return result;    }    //插入    private static <T extends Comparable<? super T>> void insert(T[] array,T value,int place){        if(((double)place)/2%1 == 0){            int index = place;            if(index!=1 && array[index/2].compareTo(value) > 0 ){                array[index] = array[index/2];                insert(array,value,index/2);            }else {                array[index] = value;            }        }else {            int index = place;            if (index!=1 && array[(index-1)/2].compareTo(value) > 0 ){                array[index] = array[(index-1)/2];                insert(array,value,(index-1)/2);            }else {                array[index] = value;            }        }    }}

堆排序的时间复杂度,最坏,平均,最好都为O(Nlog2N)。