经典排序之堆排序

1|0堆排序思路

堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:
大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;

1|1二叉树的性质

已知父节点的下标,可以获取其子节点的下标

父节点下标为 i
左子树下标为 i x 2 + 1
右子树下标为 i x 2 + 2
例: i = 1 左为3 右为4
同理知道左右子树可以知道父节点下标。

1|2思路

根据大顶堆可以知道,root节点大于所有节点为最大,那么我们可以将其移动数组最后一位,然后将 [0, n-1] 进行堆的构建 循环调用

2|0代码展示

public int[] sortArray(int[] arr) { int len = arr.length; // 初始化构建 buildMaxHeap(arr, len); // 构建之后 0下标为数组最大值,for循环从最后一位开始,交换 然后重新构建 for (int i = len - 1; i > 0; i--) { swap(arr, 0, i); len--; heapify(arr, 0, len); } return arr; } // 对半构建 private void buildMaxHeap(int[] arr, int len) { for (int i = len >> 1; i >= 0; i--) { heapify(arr, i, len); } } private void heapify(int[] arr, int i, int len) { // len 为本次构建堆的数组长度 // 获得父节点 左子树,右子树 下标位置 int left = 2 * i + 1; int right = 2 * i + 2; int largest = i; // 左子树下标小于 数组长度 并且 左子树的值大于父节点 则改变largest 标识位 if (left < len && arr[left] > arr[largest]) { largest = left; } // 右子树与左子树相同 // 这里如果左子树时已经改变 则比较左右子树大小 if (right < len && arr[right] > arr[largest]) { largest = right; } // 如果父节点标识为发生改变,则将标识为指向的位置与父节点进行交换,并重新构建 if (largest != i) { swap(arr, i, largest); // 现在发生改变,则查看改变之后的位置的变化 heapify(arr, largest, len); } } private void swap(int[] arr, int i, int j) { int next = arr[i]; arr[i] = arr[j]; arr[j] = next; }

__EOF__

本文作者Spoon | Blog
本文链接https://www.cnblogs.com/Spoonblog/p/16594778.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   SpoonBlog  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示