堆排序--大顶堆java算法实现

213 阅读1分钟

package com.xxx.service.algorithm.heapTop;

import com.alibaba.fastjson.JSON;

/**
 * Created by IntelliJ IDEA.
 * Date: 2020-05-20
 * Time: 11:38
 */
public class MaxTopHeap {

    public static void main(String[] args) {
        Integer [] dataArr = new Integer[]{1, 6, 5 ,9,9,9,11,12,17,31,21,30,20,22,9,123,5,12,5,7};
        System.out.println("原本数组" + JSON.toJSONString(dataArr));

        buildMaxTopHeap(dataArr);

        System.out.println("--------");

        System.out.println("大顶堆数组:" + JSON.toJSONString(dataArr));

        System.out.println("--------");

        minTopK(dataArr);
        System.out.print("升序:" + JSON.toJSON(dataArr));

    }

    private static void minTopK(Integer [] args) {
        for (int i = args.length - 1; i >= 0; i--) {
            swap(args, 0, i);
            heapify(args, 0, i - 1);
        }

    }

    public static void buildMaxTopHeap(Integer [] args) {
        if (args == null || args.length <= 0) {
            return;
        }

        // 初始化大顶堆
        int length = args.length;
        int lastNodeIndex = length / 2 - 1;

        for (int i = lastNodeIndex; i >= 0; i--) {
            heapify(args, i, length - 1);
        }
    }

    private static void swap(Integer[] args, int indexNode, int swap) {
        int temp = args[indexNode];
        args[indexNode] = args[swap];
        args[swap] = temp;
    }

    /**
     *
     * @param args
     * @param swapIndex 待比较交换节点
     * @param swapIndex 忽略的节点
     */
    private static void heapify(Integer[] args, int swapIndex, int ignoreStartIndex) {
        // 左节点
        int leftIndex = 2 * swapIndex + 1;
        // 右节点
        int rightIndex = 2 * swapIndex + 2;
        // 待交货节点
        int swapTempIndex = -1;
        // 存在左节点,并且比代交换节点大
        // 为什么叫ignoreStartIndex 忽略的开始索引值,是因为在排序的时候,
        // 相当于把数组缩短的意思 因为在每次顶和尾部交换的时候,其实尾部的值是等于排序好了的,可以直接忽略不出来堆结构
        if (leftIndex <= ignoreStartIndex && args[swapIndex] < args[leftIndex]) {
            swapTempIndex = leftIndex;
        }

        // 存在右节点,并且比代交换节点大
        if (rightIndex <= ignoreStartIndex && args[swapIndex] < args[rightIndex]) {
            // 存在左节点,而且左节点比代交换节点大,判断左节点和右节点的大小
            swapTempIndex = swapTempIndex != -1 && args[swapTempIndex] > args[rightIndex] ? swapTempIndex : rightIndex;
        }

        // 需要交换
        if (swapTempIndex != -1) {
            // 交换的数组,待交货节点,
            swap(args, swapIndex, swapTempIndex);
            heapify(args, swapTempIndex, ignoreStartIndex);
        }
    }
}

返回结果