堆排序的java实现

堆排序基本介绍

  • 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,他的时间复杂度为O(nlogn),他是不稳定排序。
  • 堆是具有以下性质的完全二叉树:每个节点的值都大于或等于其左右子树节点的值,称其为大顶堆,不要求节点左右子节点的大小。
  • 每个节点的值都小于或等于其左右子节点的值,称为小顶堆。
  • 大顶堆特点:arr[i] >= arr[2 * i + 1] &&arr[i] >= arr[2 * i + 2],i从0开始编号。
  • 一般升序用大顶堆,降序采用小顶堆。

堆排序基本思想

堆排序的基本思想是:

  • 将待排序的序列构造成一个大顶堆。

  • 将根节点与末尾元素进行交换,此时末尾就位最大值。

  • 将剩余的n - 1个元素重新构造成一个堆,这样就会得到n各元素的次小值。如此反复就会得到一个有序序列。

操作方法

从最后一个非叶子节点开始调整,最后一个非叶子节点为arr.length / 2 - 1,从右至左,从下至上进行调整。如图要调整的节点顺序为6 -> 9.。

在这里插入图片描述

定义一个数组来进行排序

public class HeapSort{
	public static void main(String[] args) {
        int[] arr = {4, 6, 8, 5, 9};
        heapSort(arr);
        System.out.println("排序后 = " + Arrays.toString(arr));
    }

堆排序方法
将无需序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆
将大顶堆的根节点与最后一个节点交换,这样子就把最大值
放置到最后,而剩下的是一个除根节点之外都满足大顶堆条件
的二叉树,因此此时在利用调整函数,输入待调整的非叶子
节点索引(此时只有根节点不满足,因此要调节的索引号只有0),进行变换使之成为大顶堆继续进行交换,共进行n - 1
次交换即可。

public static void heapSort(int[] arr){
        int temp = 0;
        System.out.println("堆排序:");
        //从做后一个非叶子姐点开始循环一直到整棵二叉树的根节点
        //使整棵二叉树都满足大顶堆排列
        for(int i = arr.length / 2 - 1; i >= 0; i--){
            adjustHeap(arr, i, arr.length);
        }
        for(int j = arr.length - 1; j > 0; j--){
            temp = arr[j];
            arr[j] = arr[0];
            arr[0] = temp;
            adjustHeap(arr, 0, j);
        }
        
    }

将一个数组(二叉树),调整成为一个大顶堆。
此时要进行排序的二叉树在要进行排序节点之后的非叶子结点都是满足大顶堆的条件,在进行该节点的交换后,会影响到后边的节点的排序,因此与根节点进行交换的子节点那一条分支要进行重新的排序,重新循环后该节点后变动的二叉树都满足了大顶堆的方式。

/**
 * 功能:将一个二叉树调节成一个大顶堆形式
 * 例如:int arr[] = {5, 6, 2, 7, 9},当i = 1时得到{5, 9, 2, 7, 6}
 * @param arr 是待调数组(二叉树)
 * @param i 是非叶子节点的索引号,最后一个非叶子结点索引号为arr.length / 2 - 1
 * @param lenght 表示对多少个元素继续调整,lenght是逐渐的减少
 */
    public static void adjustHeap(int[] arr, int i, int lenght){
        int temp = arr[i];  //先取出当前元素的值,保存到临时变量
        //k = i * 2 + 1, k是i的左子节点
        for(int k = i * 2 + 1; k < lenght; k = k * 2 + 1){
            if(k + 1 < lenght && arr[k] < arr[k + 1]){
                //左子节点小于右子节点的值,使其指向右子节点
                k++;
            }
            if(arr[k] > temp){
                arr[i] = arr[k];
                i = k;
            }else{
                break;
                //由于这个过程是从右往左,从上到下,所以只要在本层二叉树中根节点最大,
                //那么他一定是以他为根的整个二叉树中最大的点,因此可以直接退出
            }
        }
        arr[i] = temp;
    }
   }

经过操作后此时就完成了堆排序。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值