开发中常见的算法汇总之-堆排序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cpongo4/article/details/89333887
#### 堆排序 - 核心思想 - 堆排序其数据存储采用完全二叉树方式结构 - 排序过程就是不断**堆化**(对于每个节点的值都大于等于子树中每个节点值的堆称为大顶堆,对于每个节点的值都小于等于子树中每个节点值的堆称为小顶堆)原则进行数据调整已达到有序效果 - 堆排序需要进行堆的构建和调整,基于**穷举法思想** - 特性 - 基于二叉树结构构建排序数列,其时间复杂度由树高度决定非常稳定 - 是一种非稳定排序,因为数据按照其大堆顶或小堆顶结构进行调整时相同元素顺序会被改变 - 排序过程中元素之间交换没有额外占用辅助空间,属于原地排序 - 步骤 - 将待排序数列构建一个大顶堆/小顶堆 - 将根节点和末尾节点进行交换 - 重新进行堆的调整 - 重复上述2-3的两个步骤直到从堆上依次交换出最大值至数列中达到有序 - 图解 006tNc79ly1g1t6ap2r5zg30f70a4u0x.gif - 示例 ```java package com.lyd.algorithm.sort; import com.lyd.utils.RandomUtils; import lombok.extern.slf4j.Slf4j; /** * 描述:堆排序(数组存储) *

* - 将待排序数列构建一个大顶堆/小顶堆 * - 将根节点和末尾节点进行交换 * - 重新进行堆的调整(大顶堆/小顶堆) * - 重复上述2-3的两个步骤直到证堆达到有序 *

* * @author lyd Date 2019/4/5 ProjectName:datastructure-algo Version: 1.0 */ @Slf4j public class HeapSort { /** * 堆排序,大顶堆为例 * * @param data 待排数据集 * @return 排序后数据集 */ static int[] heapSort(int[] data) { if (null == data || data.length < 2) { return data; } //构建大顶堆 buildLargeHeap(data); log.info("buildLargeHeap:{}", data); //循环控制对顶元素和末尾元素交换次数 for (int i = data.length - 1; i > 0; i--) { //顶元素和末尾元素交换位置 int temp = data[i]; data[i] = data[1]; data[1] = temp; //除去已经交换的次数后继续调整堆上数据 heapify(data, i - 1, 1); } return data; } /** * 构建大顶堆 * * @param data 待排数据集 */ static void buildLargeHeap(int[] data) { int nodeNum = data.length - 1; //数组存储堆的规则:从数组中索引0后还是存储元素(即从第二个索引位置开始) //计算公式:父节点在数组中索引位置为i,则左孩子节点在数组索引位置为i*2,右孩子节点在数组索引位置为i*2+1 for (int i = nodeNum / 2; i > 0; i--) { //堆调整 heapify(data, nodeNum, i); } } /** * 按照大顶堆规则从上往下进行堆调整 * * @param data 构建堆的数据 * @param nodeNum 需要构建堆的节点数 * @param pNodeIndex 父节点索引 */ static void heapify(int[] data, int nodeNum, int pNodeIndex) { //左孩子节点索引 int left = pNodeIndex * 2; //右孩子节点索引 int right = pNodeIndex * 2 + 1; //默认当前父节点为最大元素 int largest = pNodeIndex; //左孩子节点大于最大元素则最大元素指向左孩子节点 if (left <= nodeNum && data[left] > data[largest]) { largest = left; } //右孩子节点大于最大元素则最大元素指向右孩子节点 if (right <= nodeNum && data[right] > data[largest]) { largest = right; } //如果最大元素为父节点自己则结束本次堆调整 if (pNodeIndex == largest) { return; } //如果最大元素为孩子节点则交换父子节点位置 int temp = data[pNodeIndex]; data[pNodeIndex] = data[largest]; data[largest] = temp; //递归往上继续调整堆的最大元素 heapify(data, nodeNum, largest); } public static void main(String[] args) { int[] sorts = new int[]{-1, 2,9,4,8,9,6,5,5,5,3}; // int[] sorts = new int[]{-1, 15, 13, 5, 6, 11, 16, 20, 17, 12, 5, 6, 11, 16, 20, 17}; // int[] sorts = RandomUtils.intArrays(16,20); //数组第一个位置不参与 sorts[0] = -1; int[] result = heapSort(sorts); log.info("sorts:{}", result);//[-1, 5, 5, 6, 6, 11, 11, 12, 13, 15, 16, 16, 17, 17, 20, 20] } } ```

猜你喜欢

转载自blog.csdn.net/cpongo4/article/details/89333887
今日推荐