堆排序原理(图)及java版代码

本文详细介绍堆排序的基本原理,并通过Java代码实现堆排序过程。文章首先构建一个完全二叉树,然后通过调整树结构实现排序,最终输出有序数组。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据结构中的堆可看做完全二叉树结构,其特性是任意一父节点的值分别大于或小于其左右子节点的值(大根堆和小根堆)

完全二叉树一般采用数组结构来表示,根据完全二叉树特性任意一父节点的值都大于(或小于)其子节点的值可知其第一个节点的值为树中的最大(最小)值,则每次将第一个父节点的值放到数组最后则可以实现排序。

首先来看一个图例:

堆排序
点击查看大图

图中详细描述了如何将一组数构建成一个完全二叉树以及通过二叉树来排序,图里已写的很清楚了,这里就不赘述了。

下面来看java版实现:

**
 * Created by white
 * USER : WHITE .
 * DATE : 2016/9/13 0013 下午 9:21.
 * HeapSortUtil.java:堆排序工具类
 */
public class HeapSortUtil {

    /**
     * 构造完全二叉树
     *
     * @param array
     */
    private void buildHeap(int[] array) {
        int lastParentIndex = getLastParentIndex(array.length);
        /*********************************************
         * 从最后一个父节点开始将树中最大值换到父节点上
         *********************************************/
        for (int i = lastParentIndex; i >= 0; i--) {
            buildTree(array, array.length, i);
        }
    }

    /**
     * 排序传入的父节点树及改动过的子树
     *
     * @param array
     * @param parentIndex
     */
    private void buildTree(int[] array, int maxIndex, int parentIndex) {
        int leftChildIndex = getLeftChildIndex(parentIndex);
        int rightChildIndex = getRightChildIndex(parentIndex);

        /***************************************************************
         * 左右节点最大值大于父节点则与父节点交换值并刷新交换后的子节点树
         **************************************************************/
        int maxValueIndex = parentIndex;
        if (leftChildIndex < maxIndex && 
                array[maxValueIndex] < array[leftChildIndex]) {
            maxValueIndex = leftChildIndex;
        }
        if (rightChildIndex < maxIndex && 
                array[maxValueIndex] < array[rightChildIndex]) {
            maxValueIndex = rightChildIndex;
        }

        if (maxValueIndex != parentIndex) {
            swapVaule(array, maxValueIndex, parentIndex);
            buildTree(array, maxIndex, maxValueIndex);
        }
    }

    /**
     * 取堆的第一个节点和最后一个节点对换并重排剩下的树
     *
     * @param array
     */
    private void sortHeap(int[] array) {
        for (int i = array.length - 1; i > 0; i--) {
            swapVaule(array, 0, i);
            buildTree(array, i, 0);
        }
    }

    /**
     * 取堆的最后一个父节点
     *
     * @param arryLength 数组长度
     * @return 返回树的最后一个父节点坐标
     */
    private int getLastParentIndex(int arryLength) {
        return (arryLength >> 1) - 1;
    }

    /**
     * 获取左子节点的下标
     *
     * @param parentIndex
     * @return
     */
    private int getLeftChildIndex(int parentIndex) {
        return (parentIndex << 1) + 1;
    }

    /**
     * 获取右子节点的下标
     *
     * @param parentIndex
     * @return
     */
    private int getRightChildIndex(int parentIndex) {
        return (parentIndex << 1) + 2;
    }

    /**
     * 交换数组中元素
     *
     * @param array
     * @param sourceIndex
     * @param targetIndex
     */
    private void swapVaule(int[] array, int sourceIndex, int targetIndex) {
        int temp = array[sourceIndex];
        array[sourceIndex] = array[targetIndex];
        array[targetIndex] = temp;
    }
}

通过以下方法调用:

    public static void main(String[] args) {
        HeapSortUtil util = new HeapSortUtil();
        int[] array = new int[]{54, 21, 32, 85, 65, 45, 12, 20, 35, 96};
        //构造完全二叉树
        util.buildHeap(array);
        //排序
        util.sortHeap(array);
        for (int i : array) {
            System.out.print(i + ", ");
        }
    }

输出结果:

12, 20, 21, 32, 35, 45, 54, 65, 85, 96, 

从结果看出已实现了堆排序,另代码里都有详细的注释,这里就不多解释了,有不明白的地方欢迎留言指出。


我的博客:blog.scarlettbai.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值