java堆排序思路及代码实现

堆排序思路:

  1. 将需要排列的数组造成大顶堆(此时堆顶根节点为最大值)
  2. 将最大值与数组末尾元素进行交换
  3. 再次将n-1个元素造堆并进行交换,循环1-3

注:因为第二步之后的堆只有根节点不符合大顶堆规定,所以第三步中造堆不需要从下往上,只需从根节点开始。

造堆思路:(length为需要排序的长度)

  1. 找到第一个非叶子节点length/2 -1设为i
  2. 若i的右子节点存在,将其与左子节点比较,较大的设为j
  3. 将arr[i]与arr[j]进行交换
  4. i=j(i指针下移到j子节点)
  5. 循环2-4
  6. 处理下一个非叶子节点length/2 -1 -1  ,循环2-6 , 直到处理完所以非叶子节点

代码实现:

package Sort;

import java.util.Arrays;

//堆排序(树的实际应用,从下往上,从左往右)
//利用大顶堆找到最大值,将最大值与最后元素进行交换,反复
public class HeapSort {
    public static void main(String[] args) {
        int arr[] = {4,6,8,5,9,-999,-1,7};
        heapSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    /**
     * 堆排序实现方法(升序)
     */
    public static void heapSort(int [] arr){
        //1.将数组造为大顶堆
        //第一个非叶子节点算法 length /2 -1
        for (int i = arr.length/2 - 1; i >= 0  ; i--) {
            adjustHeap(arr,i,arr.length);
        }
        //2.将最大值与最后元素交换
        for (int i = arr.length-1; i > 0; i--) {
            int temp =arr[0];
            arr[0] = arr[i];
            arr[i] = temp;
            //3.再次造堆,因为此时只有根节点不符合大顶堆,其余子树皆符合
            //所以这时只需要从根节点造堆
            adjustHeap(arr,0,i);
        }
    }

    /**
     * 将数组转换为大顶堆
     * @param arr 需要转换的数组
     * @param i 从该节点开始转换大顶堆,即为第一个需要处理的非叶子节点
     * @param length 需要转换的个数(找到一个最大值后应,减小1)
     */
    public static void adjustHeap(int [] arr , int i , int length){
        int temp = arr[i];//存储当前节点的值
        //比较i节点的左右节点大小
        for (int j = 2*i+1; j < length ; j = j*2+1) {
            if (j+1 < length && arr[j] < arr[j+1]){
                //左子节点小于右子节点,令j指向右子节点
                j++;
            }
            if (temp < arr[j]) {
                //子节点大于父节点,交换
                arr[i] = arr[j];
                arr[j] = temp;
                i = j ; //让指针i下移,循环比较原来i的子树
            }else {
                break;
            }
            }
        }
}

运行结果符合预期,为:

[-999, -1, 4, 5, 6, 7, 8, 9]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值