堆排序

一、堆排序

        1.实现步骤:

                          1)构造堆

                           2)得到对顶元素,这个值就为最大值

                           3)交换对顶元素和数组中最后一个元素,此时堆中最大的元素已经放到最后合适的位置

                           4)对堆进行下沉调整,重新让出过最后一个元素剩余 的元素的最大值放到堆顶

                                  注意:在下沉操作时,只需从堆的长度的一半处进行调整就行;

                                            因为:假设堆长度为k,一半处的节点的索引为k/2,那么它的左子节点的索引为k,由此看出一半处的节点为该堆的倒数第二层,则不需要再到最后一层了。

                           5)重复3、4步骤,直到剩下一个元素位置

public class HeapSort {
    //判断heap堆中索引i处的元素是否小于索引j处的元素
    public static boolean less(Comparable[] heap,int i,int j ){
        return heap[i].compareTo(heap[j])<0;
    }
    //交换heap堆中i和j处的元素
    public static void exch(Comparable[] heap,int i,int j){
        Comparable temp = heap[i];
        heap[i]=heap[j];
        heap[j]=temp;
    }
    //根据原数组source,构建堆heap
    private static void creatHeap(Comparable[] source,Comparable[] heap){
        //把source数组中的元素赋值到heap中,heap就形成一个无序的堆
          System.arraycopy(source,0,heap,1,source.length);
        //对堆进行下沉操作(从堆的长度的一半处进行调整)
           for (int i=(heap.length/2);i>0;i--){
               sink(heap,i,heap.length-1);
           }

    }
    //堆source数据进行从小到大的排序
    public static void sort(Comparable[] source){
        //构建堆
      Comparable[] heap=new Comparable[source.length+1];
        creatHeap(source,heap);
        //定义一个变量,记录未排序的元素中最大的索引
          int N=heap.length-1;
        //通过循环,交换1索引处的元素和未排序时的最大索引处的元素
        while (N!=1){
            //交换元素
            exch(heap,1,N);
            //让排序后最大元素所在的索引不要参与下沉调整
            N--;
            //对1处的元素进行下沉调整
            sink(heap,1,N);
        }
        //把heap中的数据复制到source中
        System.arraycopy(heap,1,source,0,source.length);
    }
    //再heap堆中,对target位置的元素做下沉操作,范围为0-range
    private static void sink(Comparable[] heap,int target,int range){

        while (2*target<=range){
            //找出当前子节点的较大值
            int max=0;
            if(2*target+1<=range){
                if (less(heap,2*target,2*target+1)){
                    max=2*target+1;
                }else {
                    max=2*target;
                }
            }else{
                max=2*target;
            }
            //比较当前节点和较大字节的值,小于则交换,
            if (!less(heap,target,max)){
                break;
            }
            exch(heap,target,max);
            target=max;
        }
    }
}
原文地址:https://www.cnblogs.com/cqyp/p/12588580.html