Java堆排序

x33g5p2x  于2022-02-07 转载在 Java  
字(1.5k)|赞(0)|评价(0)|浏览(694)

什么是堆

堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。

  • 大顶堆:每个结点的值都大于或等于左右子结点的值
  • 小顶堆:每个结点的值都小于或等于左右子结点的值

堆排序

堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

思路分析

1、将待排序的序列构造成一个大顶堆(升序大顶堆降序小顶堆)

2、将堆顶元素(根结点)和末尾元素进行互换。然后将剩余n-1个元素重新构造一个新的大顶堆

3、重复进行第2步操作便能得到一个有序的序列

代码实现

在这说明下面代码中的一个问题:为什么从arr.length/2-1开始?
由于堆排序近似完全二叉树假设最后一个非叶子结点下标为n
当它的左子结点为末尾元素时:2n+1 = length-1 ==> n = length/2-1
当它的右子结点为末尾元素时:2
n+2 = length-1 ==> n = length/2-(3/2)
在计算机中3/2是等于1的,所以从arr.length/2-1
可以在写代码之前看看这篇文章:二叉树顺序存储

import java.util.Arrays;
public class HeapSort {

    public static void main(String[] args) {
        int[] array = {4,6,1,2,9,8,3,5};
        heapSort(array);
        System.out.println(Arrays.toString(array));
    }

    /**
     * 堆排序
     */
    public static void heapSort(int[] arr){
        //为什么从arr.length/2-1开始?
        for (int i = arr.length/2-1; i >= 0 ; i--) {
            adjustHeap(arr,i,arr.length);
        }

        for (int j = arr.length-1; j > 0; j--) {
            int temp = arr[j];
            arr[j] = arr[0];
            arr[0] = temp;
            /*为什么从0开始?
                因为在第一次构建大顶堆后让堆顶元素和末尾元素进行交换
                而对于其他的非叶子结点所对应的子树都是大顶堆就无需调整,
                只需要堆顶元素(下标为0的非叶子结点)的子树调整成大顶堆
            */
            adjustHeap(arr,0,j);

        }
    }

    /**
     * 构建大顶堆
     * 注意:
     *      这个方法并不是将整个树调整成大顶堆
     *      而是以i对应的非叶子结点的子树调整成大顶堆
     * @param arr 待调整的数组
     * @param i 非叶子结点在数组中的索引(下标)
     * @param length 进行调整的元素的个数,length是在逐渐减少的
     */
    public static void adjustHeap (int[] arr,int i,int length){
        /*取出当前非叶子结点的值保到临时变量中*/
        int temp = arr[i];

        /*j=i*2+1表示的是i结点的左子结点*/
        for (int j = i * 2 + 1; j < length ; j = j * 2 + 1) {
            if (j+1 < length && arr[j] < arr[j+1]){ //左子结点小于右子结点
                j++; //j指向右子结点
            }
            if (arr[j] > temp){ //子节点大于父节点
                arr[i] = arr[j]; //把较大的值赋值给父节点
                //arr[j] = temp; 这里没必要换
                i = j; //让i指向与其换位的子结点 因为
            }else{
                /*子树已经是大顶堆了*/
                break;
            }
        }
        arr[i] = temp;
    }
}

运行结果

[1, 2, 3, 4, 5, 6, 8, 9]

Process finished with exit code 0

相关文章

微信公众号

最新文章

更多