堆排序

堆排序

堆排序是建立在数据结构堆上的一种操作。堆排序最简单的一种操作就是,先建立一个堆,然后依次弹出堆中的元素,使用临时数组保存。最后在把临时数组赋值给原数组。(对堆操作不熟悉的请先看数据结构之堆)
其代码为:
这里写图片描述

由于需要建一个堆,因此产生额外的空间,那么是否可以直接在元素组上建立一个堆呢? 答案是肯定的。因此,堆排序另外一个优化版本
1. 将要排序的数组arr从0到i(开始时i = arr.length),调整一个最大堆(从到大排序)
2. 因为数组是一个最大堆,因此arr[0]是最大的元素,然后交换arr[0] 与arr[i]。(那么第一个元素就到了数组的最后面), 并且i = i -1。
3. 重复过程1和2,直到i = 0。
其如下图所示。
heap sort

其完整的Java代码为:

package Sort;


import java.util.Arrays;
import java.util.Random;
import static java.lang.System.out;

/**
 * 堆排序算法类
 */
public class HeapSort {

    /**
     * 交换arr[i]和arr[j]的值
     */
    private static void swap(Comparable [] arr, int i, int j) {
        Comparable tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

    /**
     * 维护最大堆的性质
     * @param arr 数组堆
     * @param parent 以下标为parent的堆
     * @param size 堆的大小
     */
    private static  void buildHeapHelp(Comparable [] arr, int parent, int size) {
        int lch = parent*2 + 1; //左子节点index
        int rch = lch + 1; //右子节点index
        int largest = parent;    // 最大节点的index
        if (lch <= size && arr[parent].compareTo(arr[lch]) < 0)
            largest = lch;
        if (rch <= size && arr[largest].compareTo(arr[rch]) < 0)
            largest = rch;
        if (largest != parent) {
            swap(arr, parent, largest);
            buildHeapHelp(arr, largest, size);
        }
    }

    /**
     * 将数组构建成一个最大堆
     * @param arr 要构建的数组
     */
    private static void buildHeap(Comparable [] arr, int lastIndex) {

        for (int parent = (lastIndex-1)/2; parent >= 0; --parent) {
            buildHeapHelp(arr, parent, lastIndex);
        }
    }

    public static void sort(Comparable [] arr) {

        for (int i = 0; i < arr.length-1; ++i) {
            buildHeap(arr, arr.length-1-i);
            swap(arr, 0, arr.length-1-i);
        }
    }

    public static void main(String [] args) {
        Integer [] arr = new Integer[100];
        ///buildHeap(arr, arr.length-1);
        Random random = new Random();
        for(int i = 0; i < arr.length; ++i)
            arr[i] = random.nextInt(200);
        sort(arr);
        out.println(Arrays.toString(arr));

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值