堆排序的JAVA实现

网上有很多版本需要buildHeap heapify两个方法,我觉得没必要写成两个方法。

package pri.wdw.algorithm.sort;

import java.util.Arrays;

/**
 * <p>@author wdw</p>
 * <p>@date 2020/4/20 21:21</p>
 * <p>@description </p>
 */
public class HeapSort {


    /**
     * 堆的定义:
     * 完全二叉树的定义:
     * 编号为i的节点
     * 父节点:(i-1)/2
     * 左孩子:(2*i)+1
     * 右孩子:(2*i)+2
     * 最后一个非叶子节点的编号:假设堆共有n个节点,那么最后一个非叶子节点的编号为n/2 -1
     */
    public static void main(String[] args) {

        int[] arr = {9, 8, 7, 4, 5, 1, 10, 3, 3, 44, 13, 4421, -2, 4, 321, 2};

        heapSort(arr);

        System.out.println(Arrays.toString(arr));
    }


    /**
     * 思想:每次都将数组堆化,获取一个最大堆,然后将堆顶元素与末尾元素进行交换
     */
    public static void heapSort(int[] arr) {

        int maxHeapSize = arr.length;

        for (int i = maxHeapSize; i >= 2; i--) {
            heapify(arr, i);
            swap(arr, 0, i - 1);
        }
    }


    /**
     * 对任意长度数字进行堆化操作(构建大顶堆)
     *
     * @param arr
     * @param heapSize 需要堆化的数组的长度,每次p
     */
    private static void heapify(int[] arr, int heapSize) {

        //从最后一个非叶子节点开始递归
        while (heapSize >= 2) { // 也可以 heapSize / 2 - 1 >= 0即 current >= 0
            
            int current = heapSize / 2 - 1;

            //左右两个孩子节点的坐标
            int lChild = current * 2 + 1;
            int rChild = current * 2 + 2;

            //找到 leftChile,rightChild当中比较大的那一个和当前节点进行swap(需要前提保证这两个节点在堆化Size之内)
            int maxIndex = current;

            if (lChild < heapSize && rChild < heapSize) {

                int maxChild = arr[lChild] > arr[rChild] ? lChild : rChild;//先找出两个孩子两个其中大的那个

                if (arr[maxChild] > arr[current])
                    maxIndex = maxChild;

            } else if (rChild >= heapSize && lChild < heapSize && arr[lChild] > arr[current]) {
                maxIndex = lChild;
            } else if (lChild >= heapSize && rChild < heapSize && arr[rChild] > arr[current]) {
                maxIndex = rChild;
            }


            if (maxIndex != current)
                swap(arr, current, maxIndex); //交换节点


            //根据条件依次找到非叶子节点(堆的元素数为偶数,减去 1)
            if (heapSize % 2 == 0)
                heapSize -= 1;
            else
                heapSize -= 2;

        }


    }


    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }


}


posted @ 2020-05-31 00:08  wongdw  阅读(187)  评论(0编辑  收藏  举报