堆排序---递归实现

/**
 * Copyright (C), 2018-2019, LMaWC
 * FileName: application
 * Author:   neo
 * Date:     2019/5/6 10:29
 * Description:
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.threadTest;
/**
 * 〈一句话功能简述〉<br>
 * 〈堆排序实现:使用递归,易于理解〉
 *
 * @author neo
 * @create 2019/5/6
 * @since 1.0.0
 */
public class application {
    public static void main(String[] args) {
        int[] nums = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7};
        // 构建堆
        heapBuild(nums);
        // 堆排序
        heapSort(nums);
        for (int i = 0; i < nums.length; i++) {
            System.out.println(nums[i]);
        }
    }

    // 堆排序
    // 思想:把最大值放到nums end 处,然后维护1--end-1 的堆
    public static void heapSort(int[] nums) {
        int numsLen = nums.length;
        for (int i = nums.length - 1; i >=0; i--) {
            // 把最大值放在末尾
            swap(nums, 0, i);
            numsLen--;
            // 维护堆(0,i-1)的堆
            heapJustify(nums, 0, numsLen); // 这里idx 可以为0 是因为根节点的两个子树都是最大堆

        }
    }

    // 维护堆(递归实现)
    // idx为父节点
    // 思想:三个元素可以构成一个完整的最大堆,将三个最大值放到根节点,然后分别以左右子节点为根节点,维护堆,直至数组的end
    public static void heapJustify(int[] nums, int idx, int numsLen) {
        // 子节点为
        int left_idx = 2 * idx + 1;
        int right_idx = 2 * idx + 2;
        // 进行比较,找到最大值
        if (right_idx < numsLen) { // 先保证不能越界
            // 先左右子节点判断(这样可以减少交换次数)
            if (nums[left_idx] > nums[right_idx] && nums[idx] < nums[left_idx]) {
                // 交换位置
                swap(nums, idx, left_idx);
                // 以该节点为根节点继续递归
                heapJustify(nums, left_idx, numsLen);

            } else if (nums[left_idx] <= nums[right_idx] && nums[idx] < nums[right_idx]) {
                // 交换位置
                swap(nums, idx, right_idx);
                //以该节点为根节点继续递归
                heapJustify(nums, right_idx, numsLen);
            }
        }
        // 当只有左子节点时
        else if (left_idx < numsLen) {
            if (nums[idx] < nums[left_idx]) {
                swap(nums, idx, left_idx);
            }
        }


    }

    // 构建堆(调用维护堆)
    // 思想:获取距离根节点最远的父节点(nums.length/2-1),逐渐向根节点遍历至根节点
    public static void heapBuild(int[] nums) {
        // 数组从0开始,就不要-1
        for (int i = nums.length / 2 - 1; i >= 0; i--) {
            heapJustify(nums, i, nums.length);
        }
    }

    public static void swap(int[] nums, int a, int b) {
        int temp = nums[a];
        nums[a] = nums[b];
        nums[b] = temp;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值