【算法】排序_堆排序
堆排序
定义
堆排序是利用堆这种数据结构所设计的一种排序算法。
堆是一种近似完全二叉树的结构,并同时满足堆积的性质:子结点的键值或索引总是小于(或者总是大于)它的父结点
子结点的键值或索引值总是小于其父结点:大根堆
子结点的键值或索引值总是大于其父结点:小根堆
稳定性
不稳定
时间复杂度
O(N*logN)
建堆方法
HeapInsert 上浮
描述
假定事先不知道有多少个元素,通过不断往堆里面插入元素进行调整来构建堆
步骤
- 增加堆的长度,在最末尾的地方加入最新插入的元素
- 比较当前元素和它的父结点值,如果比父结点值大,则交换两个元素,否则返回
- 重复2
时间复杂度
O(N * logN)
示例
给定⽆序序列,通过 HeapInsert 建⽴⼤根堆。
插⼊节点[6],与⽗节点[3]进⾏⽐较,并交换。
插⼊节点[8],与⽗节点[6]进⾏⽐较,并交换。
插⼊节点[5],与⽗节点[3]进⾏⽐较,并交换。
插⼊节点[9],与⽗节点[5]进⾏⽐较,并交换。
节点[9]继续与⽗节点[8]进⾏⽐较,并交换。
所有节点插⼊,建堆完成。
Heapify 下沉
从最后一个非叶子结点一直到根结点进行堆化的调整。
以大根堆为例,如果当前结点小于某个自己的孩子结点,那么当前结点和这个孩子交换,并持续往下递归调整
时间复杂度
O(N)
第一个非叶子结点
如果根结点在数组中的索引为0,那么最后 一个非叶子结点计算公式lastNonLeaf = (arr.length - 2)/2
设最后一个非叶子结点的位置为x,则最后一个叶子结点一定是2x + 1
或 2x + 2
示例
- 给定⽆序序列,通过 Heapify 建⽴⼤根堆。
- 从最后⼀个⾮叶⼦节点[6]开始调整(arr.length/2-1),与其孩⼦节点中的较⼤节点⽐较,并交换。
- 调整节点[5],与其孩⼦节点中的较⼤节点⽐较,并交换。
- 继续调整节点[5],与其新孩⼦节点中的较⼤节点⽐较,并交换。
- 所有⾮叶⼦节点调整完成,建堆完成。
代码
测试用例
int arr[] = {3,6,8,5,9};
原代码
/*** @Classname HeapSort* @Description 堆排序* 时间复杂度 O(N * logN)*/
public class HeapSort {public static void main(String[] args) {// 测试数据int arr[] = {3,6,8,5,9};//测试maxHeapSort(arr,arr.length);}/*** 堆排序* @param arr* @param len*/public static void maxHeapSort(int[] arr,int len){System.out.println("初始数据:"+Arrays.toString(arr));// 最后一个非叶子结点(len-2)/2 最后一个结点:len-1for(int i = len/2 - 1; i>=0; i--){System.out.println("父结点下标:"+i);maxHeapify(arr,i,len - 1);}// 建堆完毕后结果输出System.out.println("建堆完毕后结果:"+Arrays.toString(arr)+"\n");// 先将第一个元素和已排好的元素前一位做交换(将最大的元素放到后面,类似于直接插入排序),再重新调整,直到排序完毕for (int i = len -1;i>0;i--){System.out.println("本次排序范围:0~"+(i-1));swap(arr,0,i);maxHeapify(arr,0,i-1);}System.out.println("最终结果:"+Arrays.toString(arr));}/*** 建堆* @param arr* @param start* @param end*/public static void maxHeapify(int arr[],int start,int end){// 父结点和子结点下标int dad = start;int son = dad * 2 +1;while(son <= end){ // 子结点在范围内if (son + 1 <= end && arr[son] < arr[son +1]){son++;}if (arr[dad]>arr[son]){ // 父结点大于子节点 跳出函数return;} else { // 否则交换父结点,并继续子结点和孙结点比较swap(arr,dad,son);dad = son;son = dad * 2 +1;}System.out.println("本次交换结果:"+Arrays.toString(arr));}}/*** 交换函数* @param arr* @param i* @param j*/public static void swap(int[] arr,int i ,int j){int temp = arr[j];arr[j] = arr[i];arr[i] = temp;}}
运行结果
步骤
将堆顶结点与末尾结点交换,使末尾结点最大。然后继续调整堆,再将堆顶结点与末尾结点交换,得到第二大结点。如此反复进行交换 重建
- 已有⼤根堆,对其进⾏堆排序。
- 将堆顶节点[9]与末尾节点[5]进⾏交换,交换完成后将节点[9]移出⼆叉树,并对节点[5]进⾏Heapify调
整。
- 将堆顶节点[8]与末尾节点[3]进⾏交换,交换完成后将节点[8]移出⼆叉树,并对节点[3]进⾏Heapify调
整
- 将堆顶节点[6]与末尾节点[5]进⾏交换,交换完成后将节点[6]移出⼆叉树,并对节点[5]进⾏Heapify调
整。
- 将堆顶节点[5]与末尾节点[3]进⾏交换,交换完成后将节点[5]移出⼆叉树,此时只剩⼀个节点,堆排序
结束。
【算法】排序_堆排序相关推荐
- java 小根堆 排序_堆排序(java实现)
堆排序就是用大根堆或者小根堆的节点都比左孩子 右孩子大(小)的特性 来构建有序序列. 名词解释: 大根堆:所有节点(n)都比他的左孩子(2n+1)与右孩子(2n+2)大的完全二叉树. 小根堆:所有节 ...
- java 快速排序算法简单_排序算法java版,速度排行:冒泡排序、简单选择排序、直接插入排序、折半插入排序、希尔排序、堆排序、归并排序、快速排序......
先推荐一篇关于排序算法的文章:http://www.cppblog.com/guogangj/archive/2009/11/13/100876.html 本文思路部分来源于上篇文章,但测得的结果似乎 ...
- 使用qsort对不连续的内存数据排序_一点就懂的十大经典排序算法
我是CSDN博主「雨夜※繁华」,这是我的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:一点就懂的经典十大排序算法_大数据_LH is programmin ...
- 高效排序算法——希尔排序、堆排序、归并排序、快速排序
如标题,这里讨论的是基于比较的排序算法中最高效的三种算法和希尔排序.堆排序.归并排序.快速排序的平均时间复杂度均为O(NlogN).前面有介绍过O(N2)的三种简单排序算法(见三大简单排序算法--插入 ...
- 排序算法java版,速度排行:冒泡排序、简单选择排序、直接插入排序、折半插入排序、希尔排序、堆排序、归并排序、快速排序...
先推荐一篇关于排序算法的文章:http://www.cppblog.com/guogangj/archive/2009/11/13/100876.html 本文思路部分来源于上篇文章,但测得的结果似乎 ...
- 堆排序时间复杂度_堆排序算法
堆排序是指利用堆积树这种数据结构所设计的一种排序算法,它是选择排序的一种.可以利用数组的特点快速定位指定索引的元素.堆是一个优先级队列,对于大顶堆而言,堆顶元素的权值最大.将待排序的数组建堆,然后不断 ...
- java排序算法总结_排序算法总结及Java实现
1. 整体介绍 分类 排序大的分类可以分为两种,内排序和外排序.在排序过程中,全部记录存放在内存,则称为内排序,如果排序过程中需要使用外存,则称为外排序.主要需要理解的都是内排序算法: 内排序可以分为 ...
- java冒泡排序_JAVA实现经典排序算法(冒泡排序、选择排序、插入排序、希尔排序、堆排序、归并排序、快速排序)...
冒泡排序 依次比较相邻的元素,若发现逆顺序,则交换.小的向前换,大的向后换,本次循环完毕之后再次从头开始扫描,直到某次扫描中没有元素交换,说明每个元素都不比它后面的元素大,至此排序完成. import ...
- 数据结构与算法 / 排序算法 / 堆排序
一.定义 借助堆结构实现的排序算法被称为堆排序. 二.过程说明 1.建堆 (1)方法1 原地建堆,对于数组来说,从前往后:对于树来说,从下向上. 将数组的第一个元素作为堆顶,第二个元素做向堆中插入数据 ...
- 使用qsort对不连续的内存数据排序_常见的内排序和外排序算法
常见的内排序算法 所谓的内排序是指所有的数据已经读入内存,在内存中进行排序的算法.排序过程中不需要对磁盘进行读写.同时,内排序也一般假定所有用到的辅助空间也可以直接存在于内存中.与之对应地,另一类排序 ...
最新文章
- 参加完Python培训后有哪些就业方向
- Slackware硬盘安装方法
- 基于脑电图的情绪识别BCI应用于DOC患者
- hive python udf_python udf方法
- 模拟浏览器自动化测试工具Selenium之五Centos系统命令行下部署selenium环境试验
- ObjectInputStream和ObejctOutputStream
- python求线段长度_python微元法计算函数曲线长度的方法
- 1.10 编程基础之简单排序 06 整数奇偶排序 python
- 成为大数据顶尖程序员,先过了这些Hadoop面试题!(附答案解析)
- 仿新浪微博实现ListBox下拉刷新和到底部自动加载
- 2018华为软件精英挑战赛个人总结
- 基因家族进化分析之DNA序列批量获取
- 【STM32】中断和中断优先级理解
- 实验一.MATLAB求解优化问题
- 【知识图谱】Neo4j的基本使用及思知1.4亿三元组数据构建知识图谱
- PHP简易开发的问卷调查系统
- 【经验分享】记录自己使用markdown开始写Blog
- 25个有用的 JavaScript 单行代码
- 利用XP ie浏览器的漏洞获取shell
- 面对金九银十你真的准备好了吗?
热门文章
- (转)互联网投顾平台的监管风险:和讯信息
- 开放、创新、合作,共赢多样性计算新时代
- 【数据预测】基于matlab双向长短时记忆(BiLSTM)数据预测【含Matlab源码 1824期】
- 毕设题目:Matlab优化充电
- 【优化算法】乌燕鸥优化算法(STOA)【含Matlab源码 1431期】
- 用python设计图案_用 Python 打造属于自己的GUI图形化界面
- 若泽数据 巨人_面部识别巨人拒绝分享有关其算法数据集的详细信息
- keras pytorch_使用PyTorch重新创建Keras功能API
- 使用Pytorch的LSTM文本分类
- aba问题实际中有什么影响_实际影响是什么?