0
点赞
收藏
分享

微信扫一扫

数据结构与算法—回顾堆排序

at小涛 2022-01-09 阅读 66

前言

知识它忘得太快了,而自己又处于过五关斩六将的状态,冲啊~

思路

堆排序很经典,这里不追求赘述堆的相关知识点,而是视作已经堆结构有一定了解

  • 堆是一种完全二叉树的结构,分为大顶堆和小顶堆,大顶堆就是父节点的值比左右子结点的值大,小顶堆则相反
  • 堆排序的时间复杂度是O(n*log2n),最好最坏都是这个
  • 堆排序(排序结果从小到大)分为两步,第一步是把给定的一个数组初始化为一个大顶堆,第二步是将第一个元素与最后一个元素交换,因为第一个元素一定是最大的,之后再次进行大顶堆的调整,交换,调整……………………,最后将得到一个升序队列。

Java 实现

class Solution {
    public int[] sortArray(int[] nums) {
        heapSort(nums);
        return nums;
    }
    // 堆排序
    public void heapSort(int[] nums){
        // 初始建堆
        for(int i= nums.length/2;i>=0;i--){
            HeapAdjust(nums,i,nums.length);
        }
        // 进行n-1次循环,每次循环完,0下标位置就是最大的元素,我们把该元素放到数组末尾
        for(int i = nums.length-1;i>0;i--){
            int t = nums[i];
            nums[i] = nums[0];
            nums[0] = t;
            HeapAdjust(nums,0,i);
        }


    }

    public void HeapAdjust(int[] nums,int parent,int len){
        // 保存当前父节点的值
        int parentValue = nums[parent];
        // 找到左节点
        int childIndex = 2 * parent +1;
        while(childIndex<len){
            // 如果有右节点,并且大小是比左节点大的,那么选取右节点,后续会跟父节点进行比较
            if(childIndex+1<len && nums[childIndex]<nums[childIndex+1]){
                childIndex++;// 此时index为右结点
            }
            // 如果此时父结点已经比孩子结点都大,直接跳出即可,根本不需要交换,那么后面也不会有下沉情况
            if(parentValue>nums[childIndex]) break;

            // 否则进行交换
            nums[parent] = nums[childIndex];
            nums[childIndex] = parentValue;
            
            // 交换完之后,进行一个"下沉"操作
            parent = childIndex;
            childIndex = parent * 2 + 1; 
        }

    }
}
举报

相关推荐

0 条评论