美文网首页
堆排序(Java版)

堆排序(Java版)

作者: lkmc2 | 来源:发表于2018-03-08 23:08 被阅读19次

堆排序的原理是先构造一个大顶堆,每次弹出堆中一个最大元素填充到数组倒数第N的位置(逆序),即可将数组由小到大进行排序。

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

/**
 * Created by lkmc2 on 2018/3/8.
 * 堆排序
 */

//堆结构
class MaxHeap {
    private int[] data; //该数组从1开始使用,0不使用
    private int count; //数组当前存值的数量
    private int capacity; //数组总长度

    public MaxHeap(int capacity) {
        this.data = new int[capacity + 1]; //数组的0下标不用,从1开始存值
        this.count = 0;
        this.capacity = capacity;
    }

    public MaxHeap(int[] arr, int n) {
        this.data = new int[n + 1];
        this.capacity = n;
        for (int i = 0; i < n; i++)
            data[i + 1] = arr[i];

        this.count = n;

        //从第一个非叶子节点的父元素开始进行shiftDown操作
        //该父元素的位置为数组当前存值的长度的二分之一,即 count / 2
        for (int j = count / 2; j >= 1; j--)
            shiftDown(j); //将处于下标为j的元素向下移动到正确的位置
    }

    //取出优先级最大的一个元素,也就是下标为1的元素,并把最后一个元素放到下标为1的地方,
    // 然后位置的元素不断和下面的元素比较,直到找到合适的位置
    public void shiftDown(int k) {
        while (2 * k <= count) {
            int j = 2 * k; //在此轮循环中,data[k]和data[j]交换位置

            if (j + 1 <= count && data[j + 1] > data[j])  //右节点比左节点值大
                j += 1; //将j坐标移动到右节点

            if (data[k] > data[j]) //该节点比左节点和右节点的值都大,结束循环,调整结束
                break;

            int temp = data[k]; //该节点与左节点或右节点交换
            data[k] = data[j];
            data[j] = temp;

            k = j; //更新该节点坐标
        }
    }

    public void shiftUp(int k) { //插入元素后,该元素与父节点比较,大于父节点则交换位置
        while (k > 1 && data[k / 2] < data[k]) { // k/2 表示父节点的坐标,父节点小于该元素
            int temp = data[k / 2]; //交换该元素与父节点的值
            data[k / 2] = data[k];
            data[k] = temp;

            k /= 2; //更新交换后的坐标
        }
    }

    void insert(int item) { //插入元素
        if (count + 1 > capacity) return;

        data[count + 1] = item; //添加新元素到数组
        count++;
        shiftUp(count); //与父节点比较找到该元素的正确位置
    }

    int extractMax() { //取出最大值
        if (count <= 0) return -1;
        int result = data[1]; //获取第一个元素的位置

        int temp = data[1]; //交换第一个元素与最后一个元素的位置
        data[1] = data[count];
        data[count] = temp;

        count--;
        shiftDown(1); //将处于下标为1的元素向下移动到正确的位置
        return result;
    }

    int size() { //获取当前数组中元素个数
        return count;
    }

    boolean isEmpty() { //获取数组是否为空
        return count == 0; 
    }
}

public class HeapSort {

    public static void heapSort1(int[] arr, int n) { //堆排序1(从小到大)
        MaxHeap maxHeap = new MaxHeap(n);
        for (int i = 0; i < n; i++)
            maxHeap.insert(arr[i]); //将数组中的值插入堆

        for (int j = n - 1; j >= 0; j--)
            arr[j] = maxHeap.extractMax(); //取出最大值,存回数组
    }

    //堆排序2(从小到大,使用Heapify,效率比堆排序1高)
    public static void heapSort2(int[] arr, int n) { 
        MaxHeap maxHeap = new MaxHeap(arr, n);

        for (int j = n - 1; j >= 0; j--)
            arr[j] = maxHeap.extractMax(); //取出最大值,存回数组
    }

    public static void main(String[] args) {
        int[] arr1 = {88,34,18,47,83,79,20};
        heapSort1(arr1, arr1.length);
        printInfo(arr1);

        int[] arr2 = {88,34,18,47,83,79,20};
        heapSort2(arr2, arr2.length);
        printInfo(arr2);
    }

    public static void printInfo(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
}
堆排序运行结果

相关文章

  • 堆排序(Java版)

    堆排序的原理是先构造一个大顶堆,每次弹出堆中一个最大元素填充到数组倒数第N的位置(逆序),即可将数组由小到大进行排...

  • C++的模板堆排序

    normal版的堆排序

  • 堆排序(非递归版)

    时间复杂度是O(nlogN) 但是不常用堆排序,因为堆排序不稳定 Java实现

  • JavaScript的排序算法——堆排序

    堆排序(Heap Sort) 堆排序(Heap Sort)是一种基于比较的排序算法。堆排序可以被认为是一种改进版的...

  • 排序

    八大排序算法 一、归并排序 递归及非递归的JAVA实现 二、快速排序 快排算法JAVA实现 三、堆排序 堆排序堆排...

  • 最大堆应用: 堆排序 --- Java版

    堆定义 生活中需要使用优先队列, 比如cpu调度算法,线程调度算法都需要把优先级高的任务装入一个优先队列Prior...

  • 排序算法-堆排序

    参考: Java排序算法(五):堆排序 【算法与数据结构】图说堆排序 【数据结构】排序算法:希尔、归并、快速、堆排...

  • 排序算法08:优先队列与堆排序

    堆排序一种是基于二叉堆的排序。本文将从优先队列讲起,循序渐进的实现堆排序。这也是《算法》第四版上讲解堆排序的大致章...

  • java堆排序

    什么是堆排序:图解堆排序堆排序:利用了堆这种数据结构堆数据结构:特殊的完全二叉树,因为具有以下的特点:1)每个结点...

  • 堆排序(java)

    将待排序序列构造成一个大顶堆,此时序列的最大值就是堆顶元素,将它和数组的末尾元素交换,再将剩余的n-1个元素构造成...

网友评论

      本文标题:堆排序(Java版)

      本文链接:https://www.haomeiwen.com/subject/enyufftx.html