美文网首页
java实现堆排序

java实现堆排序

作者: 修行者12138 | 来源:发表于2020-12-06 08:52 被阅读0次
package com.crazy.leetcode;

import java.util.Arrays;

/**
 * 堆排序(大顶堆)
 */
public class HeapSort {
    /**
     * 初始无序数组
     */
    private int[] nums;

    /**
     * nums数组长度
     */
    private int length;

    /**
     * 堆末已排好序的节点数量
     */
    private int orderCount;

    /**
     * 对数组升序排序
     * @param nums 无序数组
     */
    private void heapSort(int[] nums) {
        this.nums = nums;
        length = nums.length;
        orderCount = 0;
        buildHeap();
        adjustHeap();
    }

    /**
     * 构造大顶堆
     */
    private void buildHeap() {
        // 找到最后一个非叶子节点,从右到左,从下到上遍历到根节点,对每个节点进行调整
        // 文末会解释为什么最后一个非叶子节点的下标是length / 2 - 1
        for (int i = length / 2 - 1; i >= 0; i--) {
            adjustNode(i);
        }
    }

    /**
     * 调整堆:
     * 1.交换根节点与最后一个节点(不包括已排好序的节点)
     * 2.堆末已排好序的节点数量 + 1
     * 3.对未排好序的部分,构造大顶堆
     * 4.重复以上步骤,直到已排好序的节点数量 = 总节点数
     */
    private void adjustHeap() {
        while (orderCount < length) {
            swap(0, length - 1 - orderCount);
            orderCount ++;
            for (int i = (length - orderCount) / 2 - 1; i >= 0; i--) {
                adjustNode(i);
            }
        }
    }

    /**
     * 调整节点:若左节点或右节点大于当前节点,把当前节点与左右节点中较大者交换
     * @param i 当前节点下标
     */
    private void adjustNode(int i) {
        // 当前节点的值
        int curVal = nums[i];
        // 左节点的值
        int leftVal = nums[2 * i + 1];
        // 右节点不为空
        if (2 * i + 2 < length - orderCount) {
            // 右节点的值
            int rightVal = nums[2 * i + 2];
            if (rightVal > leftVal && rightVal > curVal) {
                // 交换当前节点和右节点
                swap(i, 2 * i + 2);
                return;
            }
        }
        if (leftVal > curVal) {
            // 交换当前节点和左节点
            swap(i, 2 * i + 1);
        }
    }

    /**
     * 交换元素
     * @param i 元素i
     * @param j 元素j
     */
    private void swap(int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

验证

public static void main(String[] args) {
    int[] nums = new int[]{4, 6, 8, 5, 9, 11, 13, 3, 5, 17};
    new HeapSort().heapSort(nums);
    System.out.println(Arrays.toString(nums));
}

[3, 4, 5, 5, 6, 8, 9, 11, 13, 17]

堆排序中,需要求最后一个非叶子节点的下标,公式为nums.length / 2 - 1,证明如下:
已知堆为完全二叉树,完全二叉树有以下特性:序号(从0开始)为i的节点,其左节点序号为2i+1,其右节点序号为2i+2
设最后一个非叶子节点序号为i,总节点数为n,层数为k,分两种情况讨论
1.最后一个非叶子节点没有右节点,即左节点序号为2 * i + 1,该节点同时是整个树最后一个节点,即2 * i + 1 = n,得出i = (n - 1) / 2,这种情况下,前k - 1层的节点数2 ^ (k - 1) - 1是奇数,最后一层也是奇数,所以n一定是偶数,所以 (n - 1) / 2 = n / 2 - 1
2.最后一个非叶子节点有右节点,即右节点序号为2 * i + 2,该节点同时是整个树最后一个节点,即2 * i + 2 = n,得出i = (n - 2) / 2,这种情况下,前k - 1层的节点数2 ^ (k - 1) - 1是奇数,最后一层是偶数,所以n一定是奇数,所以 (n - 2) / 2 = n / 2 - 1

相关文章

  • 排序

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

  • 堆排序(非递归版)

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

  • 堆排序java实现

    //堆排序://基本思想://首先要了解堆这种数据结构://堆是实质上是一个满足如下条件的完全二叉树:树中任意非叶...

  • Java 实现 堆排序

    关键点 : 平衡二叉树; 任意父节点都大于(小于)子节点; 用数组来储存。(父节点为arr[i],则左节点arr[...

  • 堆排序(java实现)

    一、前言 堆是一个数组,它可以看成近似的完全二叉树。表示堆的数组包括两个属性:A.length数组元素的个数,A....

  • 堆排序(Java实现)

    封装成类: 测试: 输出:[-1, 9, 0, 6, 5, 8, 2, 1, 7, 4, 3][-1, 0, 1,...

  • 堆排序算法(Java实现)

    原始堆如下: 堆排序算法 构造初始堆,从最后一个非叶节点开始调整选出叶子节点中比自己大的一个交换,如果交换后的叶子...

  • JS实现堆排序

    原理 堆排序原理 实现 说明 堆排序对大文件很有效 堆排序是不稳定排序

  • 堆排序---基础篇

    本文主要介绍堆排序的一些基本过程和分析。 大纲 堆排序简介 堆排序代码实现 1. 堆排序简介 1.1 堆排序的存储...

  • 堆排序

    目录 1.堆排序介绍 2.堆排序图文说明 3.堆排序的时间复杂度和稳定性 4.堆排序实现 堆排序介绍 堆排序(He...

网友评论

      本文标题:java实现堆排序

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