【七大排序】原地堆排序的实现(Java图解)

目录

1.数组排序

2.原地堆排序

3.图解(以数组单调不减用大堆为例)

4.代码实现:

5.测试

测试结果: 


1.数组排序

  1. 我们可以运用堆这个算法对数组进行排序的实现,比如创建一个新的堆,利用堆的add()遍历数组将元素加入堆中,但是这样会增加O(n)的辅助空间,那么有没有一种办法,利用堆使用O(1)的空间就实现数组排序呢?
  2. 答案当然是有的,就是我们接下来讲的原地堆排序

2.原地堆排序

  1. 首先我们将数组进行堆化,(数组单调不减用大堆,单调不增用小堆
  2. 堆顶元素与堆末尾的元素进行交换,可取size--,这样最末尾的元素就已经排好序了
  3. 堆顶元素下沉,继续和最后一位没排好序的元素进行交换,重复23操作
  4. 直到换到堆顶最后一位元素,数组内所有元素都已排好序,退出循环

3.图解(以数组单调不减用大堆为例)

步骤2中,蓝色代表已排好序的元素,绿色代表正在下沉的元素

4.代码实现:

public static void heapSort(int [] arr){
        //堆化
        //从倒数第一个不是叶子节点开始遍历下沉
        int k = (arr.length - 1 - 1)/2;
        for (int i = k; i >= 0 ; i--) {
            siftDown(arr,i,arr.length);
        }
        //此时小堆已建立完成
        for (int i = arr.length - 1; i > 0 ; i--) {
            //交换首尾元素
            swap(arr,0,i);
            //首元素下沉
            siftDown(arr,0,i);
        }
    }

    public static void siftDown(int[] arr, int k, int size){
        //保证有左子树
        while ((k * 2) + 1 < size){
            int j = (k*2) + 1;
            //有右子树并且右子树比左子树小
            if(j + 1 < size && arr[j + 1] < arr[j]){
                j = j + 1;
            }
            //此时找到左右子树最小值
            if(arr[k] > arr[j]){
                swap(arr,j,k);
                k = j;
            }else {
                break;
            }
        }
    }

5.测试

数据量小的情况下测试数据可能不准,所以我们用随机数随机产生一万个随机数,然后调用堆原地排序方法,然后用isSorted()测试结果是否有序

    public static boolean isSorted(int[] arr){
        for (int i = 0; i < arr.length - 1; i++) {
            if(arr[i] < arr[i + 1]){
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        Random random = new Random();
        int n = 1_0000;
        int[] data= new int[n];
        for (int i = 0; i < n; i++) {
            data[i] = random.nextInt(100);
        }
        System.out.println("调用堆排序之前,数组元素是否有序?");
        System.out.println(isSorted(data));
        heapSort(data);
        System.out.println("调用堆排序之后,数组元素是否有序?");
        System.out.println(isSorted(data));
    }

测试结果: 

我们可以看到 ,经过原地堆排序后的数组变得有序了,证明我们的代码是没问题哒

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值