您的位置:首页 > 编程语言 > Java开发

HeapSort的java语言实现

2015-06-01 16:22 399 查看

堆排序的实现

思想如下

第一步:建堆(最大堆或最小堆)

第二步:排序

要注意的是:建堆和排序的过程中都会进行堆的维护,以最大堆为例:节点的值不小于左右两个子节点(若存在)的值,也不大于父节点的值;若不满足这样的情况,则需要调整



java实现的代码如下:

package org.wrh.algorithmimplements;

import java.util.Arrays;

//堆排序的实现
/*
 * 堆排序需要两个步骤:
 * 第一:建堆
 * 第二:排序
 * 其中建堆和排序的过程中都需要维护堆的性质
 * */
public class HeapSortImplement {

    public static void main(String[] args) {
        int []arr={9,8,7,4,6,5,4,9,3,1,8,0,2};
        System.out.println("排序前的数组如下:"+Arrays.toString(arr));
        //建堆
        buildHeap(arr,arr.length);
        //排序
        heapSort(arr,arr.length);

        System.out.println("排序后的数组如下:"+Arrays.toString(arr));
    }

    /*
     * 完成对数组的排序
     * 思想如下:因为我们采用的是最大堆,因此我们将一个元素与最后的一个元素交换,然后调用heapify来调整,就这样继续下去,直至结束
     * */
    private static void heapSort(int[] arr, int length) {
        int heap_size=length;
        while(heap_size>0){
            heap_size--;//将堆的大小减一,使得将数组中的最后面已经排好序的在堆中隐藏掉
            swap(arr,0,heap_size);//注意这里是下标为零的位置与最后的位置进行交换;容易写成“1”
            headify(arr,0,heap_size);

        }

    }
    /*
     * 此函数是将任意数组建成一个最大堆
     * 建堆的要点在于:由于(n/2)+1到n的下标元素是堆的叶子节点,首先将这些叶子节点各看成一个单元素的堆,然后逐级往上面进行调整使其成为最大堆
     * */
    private static void buildHeap(int[] arr, int length) {
        for(int i=length/2-1;i>=0;i--){
            //调用维护堆的函数
            headify(arr,i,arr.length);

        }
    }

    /*
     * 当我们对堆进行改变之后,我们需要对堆进行调整,使其具有最大堆的性质,此函数就完成此功能
     * */
    private static void headify(int[] arr, int i,int heap_size) {
        //i位置的值可能不是最大值,而i位置的左孩子和右孩子还具有最大堆的性质,故需要调整
        int left=2*i+1;
        int right=2*i+2;
        int largest;
        /*
         * 注意:首先要判断的是left和right是否在数组的边界之内;然后才比较出最大值进行交换,最后再维护最大堆性质
         * */
        if(left<heap_size&&arr[left]>arr[i]){
            largest=left;

        }
        else {
            largest=i;
        }
        if(right<heap_size&&arr[right]>arr[largest]){
            largest=right;

        }
        /*
         * 这里要注意的是:只有当i与largest不相等的时候,才交换,若相等则说明的是此时是满足最大堆性质的
         * */
        if(i!=largest){
            swap(arr,i,largest);
            headify(arr,largest,heap_size);
        }

    }

    /*
     * 用来调整数组中两个位置的顺序
     * */
    private static void swap(int[] arr, int i, int largest) {
        if(i!=largest){
            int temp=arr[i];
            arr[i]=arr[largest];
            arr[largest]=temp;

        }
    }

}


代码中注释写的比较详细,这里就不在解释。

总结

堆排序的时间复杂度为:O(nlogn)

堆排序与插入排序类似,都是原址排序

堆排序与归并排序在时间复杂度上一样,相比之下,快排要更好,因为快排是平均性能下的时间复杂度为O(nlogn)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: