算法导论:堆排序

堆是一个数组,它可以被看成一个近似的完全二叉树,树上的每一个结点对应数组中的一个元素。除去最底层外,该树是完全充满的,而且从左到右填充。

用数组A表示堆,从数组第1个元素开始,数组中第i(1<=i <=n)个元素,其父结点,左孩子,右孩子的下标如下

    // 父结点public  int parent( int i){return i/2;}// 左孩子public int left(int i){return 2*i;}// 右孩子public int right(int i){return 2*i+1;}

 当数组起始下标是0的时候,其父结点,左右孩子结点如下

    // 父结点public  int parent( int i){return (i-1)/2;}// 左孩子public int left(int i){return 2*i+1;}// 右孩子public int right(int i){return 2*i+2;}

 

堆可以分为大顶堆和小顶堆

大顶堆:结点 i 的值 都大于其左右孩子结点的值

小顶堆:结点 i 的值 都小于其左右孩子结点的值

二叉树的形式与数组形式表达堆之间元素的关系

 

练习1,高度为h的堆,元素最少和最多是多少?

最多:这个完全二叉树第h层元素填满:2^h - 1

最少:第h-1层填满,第h层只有一个元素:2^(h-1) -1 + 1 = 2^(h-1)

说明:h=1 表示第一层

练习2,含有n个元素的堆的高度是 [lgn]

练习3,当用数组存放堆的时候,堆的元素时候n,求叶子结点下标

 

构建大顶堆

max-heapify 用于维护一个大顶堆。它的输入是一个数组A和下标i。在调用max-heapify的时候,假定根结点left(i) 和right(i) 的二叉树都是大顶堆,但这时A[i]有可能小于其中的一个孩子,这样就违背大顶堆的性质。我们需要进行调整,选取left(i) right(i) 对应结点较大的一个和 i 位置处的结点进行互换。

建堆代码如下

    /*** 调整堆元素* @param A* @param n* @param i*/public void max_heapify(int[] A ,int n,int i){// 左孩子结点int l = left(i);// 右孩子结点int r = right(i);// 最大结点下标int largest = -1;// 与左孩子判断if(l<= n && A[l] > A[i])largest = l;elselargest = i;// 与右孩子判断if(r <=n && A[r] > A[largest])largest = r;// i 结点不是最大值maxId 和i 结点进行交换if(largest != i ){swap(A,largest,i); max_heapify(A,n,largest);}}/*** 交换* @param A* @param l* @param r*/public void swap(int [] A,int l,int r){int tmp = A[l];A[l] = A[r];A[r] = tmp;}

 

 时间复杂度:O(lg(n))

说明:

在 i left(i) right(i) 三个结点中,选取其对应的值最大的结点和 i 结点的值进行交换。在交换后,下标为largest的结点的值是原来的A[i] 的值,largest所在的结点的子树可能违反大顶堆的性质,需要对该子树递归调用max-heapify

这里的假设是 以left(i) right(i) 为结点的堆已经是大顶堆,所以这个时候,我们只需要上面的三个元素就好了

算法导论例子

 

改成循环代码

    /*** 调整堆元素* @param A 数组存放堆* @param n 数组的数量 从 1 - n 开始* @param i 需要调整的堆 元素 位置 */public void max_heapify1(int[] A ,int n,int i){int l = -1;int r = -1;int largest = -1;while(true){l = left(i);r = right(i);if(l<=n && A[l] > A[i])largest = l;else largest = i;if(r <=n && A[r] > A[largest])largest = r;if(largest!=i){swap(A,largest,i);//更新i 的值相当的递归调用i = largest;// 相等 对左右子树不影响}else{break;}    }}

 

建堆

自底向上的方法,利用max-heapify 把一个大小为n 的数组A[1,...,n] 转换成大顶堆。子数组A[[n/2] +1,...,n] 中的元素是树的叶子结点。每个叶子结点可以看成一个大顶堆,所有在建堆的时候从 n/2 的元素开始 一直到 第 1 的元素。

为什么这样做?因为对当前结点进行操作时能够保证以当前结点为根的树的子树都已经是最大顶堆。这是从后像前的过程,先把底层的大顶堆构建好,再逐步的构建上层的大顶堆,在一定程度上减少了不比较的操作。如果是从1 到 n/2 的时候,对于新加入的元素,前面已经构建好的大顶堆可能都需要进行更新。比如,我们已经在第100层, 新插入的元素比之前堆内的元素都大,如100000,前面已经构建好的99层都要进行调整。

    /*** 建立大顶堆* @param A* @param n*/public void build_max_heap(int[] A,int n){for(int i = n/2;i>=1;i--){max_heapify(A,n,i);}}

 

时间复杂度:O(nlog(n))

算法导论建堆例子

堆排序算法

初始时候,利用build_max_heap将输入数组A[1,..,n] 建成大顶堆,这里A[1]一定是最大的元素,将A[1]与A[n]互换,再对A[1,...,n-1] 调整为大顶堆,然后A[1]与A[n-1]元素互换,再对A[1,...,n-2] 调整为大顶堆,如此循环下去

    /*** 堆排序 升序* @param A* @param n */public void heap_sort(int[] A,int n){build_max_heap(A,n);for(int i = n;i>=2;i--){swap(A,i,1);max_heapify(A,i-1,1);}}

堆排序的时间复杂度:O(nlogn)

算法导论例子

 

所有程序

package heapSort;class heap{/*** 堆排序 升序* @param A* @param n */public void heap_sort(int[] A,int n){build_max_heap(A,n);for(int i = n;i>=2;i--){swap(A,i,1);max_heapify(A,i-1,1);}}/*** 建立大顶堆* @param A* @param n*/public void build_max_heap(int[] A,int n){for(int i = n/2;i>=1;i--){max_heapify(A,n,i);}}/*** 调整堆元素* @param A 数组存放堆* @param n 数组的数量 从 1 - n 开始* @param i 需要调整的堆 元素 位置 */public void max_heapify1(int[] A ,int n,int i){int l = -1;int r = -1;int largest = -1;while(true){l = left(i);r = right(i);if(l<=n && A[l] > A[i])largest = l;else largest = i;if(r <=n && A[r] > A[largest])largest = r;if(largest!=i){swap(A,largest,i);//更新i 的值相当的递归调用i = largest;// 相等 对左右子树不影响}else{break;}    }}/*** 调整堆元素* @param A* @param n* @param i*/public void max_heapify(int[] A ,int n,int i){// 左孩子结点int l = left(i);// 右孩子结点int r = right(i);// 最大结点下标int largest = -1;// 与左孩子判断if(l<= n && A[l] > A[i])largest = l;elselargest = i;// 与右孩子判断if(r <=n && A[r] > A[largest])largest = r;// i 结点不是最大值maxId 和i 结点进行交换if(largest != i ){swap(A,largest,i); max_heapify(A,n,largest);}}/*** 交换* @param A* @param l* @param r*/public void swap(int [] A,int l,int r){int tmp = A[l];A[l] = A[r];A[r] = tmp;}// 父结点public  int parent( int i){return i/2;}// 左孩子public int left(int i){return 2*i;}// 右孩子public int right(int i){return 2*i+1;}
}
public class heapSort {public static void main(String[] args) {heap h = new heap();// 第一个元素不考虑int[] A = new int[]{-1,4,1,3,2,16,9,10,14,8,7};int n = A.length-1;//h.build_max_heap(A, n);//printA(A);//16 14 10 8 7 9 3 2 4 1 //16 14 10 8 7 9 3 2 4 1 
        h.heap_sort(A, n);System.out.println();printA(A);}public static void printA(int[] A){for(int i:A){System.out.print(i+" ");}}}
View Code

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/543372.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

扩展坞可以把手机投到显示器吗_解锁4K 60Hz毕亚兹USB Type-C扩展坞体验

现在很多白领办公、学生上网课都会使用到笔记本电脑&#xff0c;尤其是近两年的轻薄本&#xff0c;为了追求轻量化&#xff0c;砍掉了原本很多的接口&#xff0c;转而使用Type-C来代替&#xff0c;从而导致接驳外设的时候非常不方便。特别是那种只给了一个USB标准接口的电脑&am…

Android view.settran,Android RecyclerView从入门到玩坏

目录前言基础使用分隔线点击监听搭配CardView更丰富的条目增删条目快速添加视图让RecyclerView支持复杂视图最后前言RecyclerView在Android界面开发当中是很重要的, 那掌握它也是很必要的. 但是有些时候会觉得它很厚重, 这里就从RecyclerView的基础一直说到扩展, 让你把Recycle…

python提取英文单词 每行显示一个_使用python对文件中的单词进行提取

由于需要使用一个纯单词组成的文件&#xff0c;在网上下载到了一个存放单词的文件&#xff0c;但是里面有中文的解释&#xff0c;那就需要做一下提取了。 文本的形式如下&#xff1a;所见即所得&#xff0c;这个文本是有规律的&#xff0c;每个单词为一行&#xff0c;紧接着下一…

微服务feignclient_搞微服务用阿里开源的 Nacos 真香啊

本文适合有 Java 基础知识的人群本文作者&#xff1a;HelloGitHub-秦人HelloGitHub 推出的《讲解开源项目》系列&#xff0c;今天给大家带来一款开源 Java 版可以实现动态服务发现&#xff0c;配置和服务管理平台——Nacos&#xff0c;它是阿里巴巴团队推出的&#xff0c;符合国…

华为mate40搭载鸿蒙,华为mate40搭载鸿蒙还是EMUI11,答案来了

原标题&#xff1a;华为mate40搭载鸿蒙还是EMUI11&#xff0c;答案来了今年秋季苹果要发布首款5G版iPhone手机iPhone12&#xff0c;搭载A14处理器首发iOS14系统。而华为也要发布新款旗舰手机华为mate40系列手机&#xff0c;搭载华为麒麟1020处理器&#xff0c;首发EMUI11系统。…

称重管理系统如何修改重量_无人值守称重系统硬件配置和作用

1. 视频监控抓拍系统软件配合设摄像头在保存数据的同时抓拍&#xff0c;防止车辆或者人为的舞弊行为2. 红外定位在地磅否的两侧各安装一对红外对射&#xff0c;通过信号线连接到开关&#xff0c;当红外的光束被阻挡时&#xff0c;红外定位系统将自动发出警告&#xff0c;禁止称…

在建工程直接费用化_威县垃圾发电在建项目被罚后续:现已整改

新京报讯(记者 李大伟)3月11日&#xff0c;针对此前因环保问题被处罚一事&#xff0c;威县垃圾发电在建项目(下称威县项目)的项目方宁夏电力建设工程公司相关负责人罗中辉表示&#xff1a;目前&#xff0c;该项目已整改完成。“所有道路上的浮土已彻底清扫&#xff0c;所有的裸…

centos 断电重启后,文件系统损坏修复

为什么80%的码农都做不了架构师&#xff1f;>>> centos 断电重启后&#xff0c;由于文件系统损坏&#xff0c;无法正常开机&#xff0c;常常出现“an error occurred during the file system check” 提示&#xff0c;就是说系统文件损坏啦&#xff0c;这时候要用f…

如何对聚类结果进行分析_如何更合理地给聚类结果贴标签——由一个挖掘学生用户的项目说开去...

”聚类一时爽&#xff0c;判断两行泪“——这是解决任何一个无监督问题时都会面临的苦恼&#xff1a;最近接到了一个无监督问题的项目——给一群无标签的结构化数据贴标签&#xff0c;随后我便立即展开了工作&#xff0c;首先开始查阅资料&#xff0c;然后把EDA(数据探索) 、特…

查看文件二进制编码_小白也能学会系列:用python文件读写代码实例!(简单案例)...

前言&#xff1a;不久之前&#xff0c;从一个.dat文件中读取波形数据&#xff0c;通过一个自编码网络进行异常检测。所以特意在此写出来&#xff0c;咱从最基础的文件读写开始吧。先说数据&#xff0c;是一个int16型的数组。说是数组&#xff0c;但是读取也并不简单。众所周知&…

stm32 ucosii消息队列 串口_STM32F1的UART4串口配置

注意是UART4&#xff0c;不是USART4在stm32中UART和USART是不相同的USART是通用同步/异步串行接收/发送器UART是通用异步收发传输器简单区分同步和异步就是看通信时需不需要对外提供时钟输出&#xff0c;我们平时用的串口通信基本都是 UART。USART支持同步模式&#xff0c;因此…

程序员微信头像_微信头像暴露了你的层次:层次越低的人,越喜欢用这些头像...

这个话题&#xff0c;原本很轻松。但往细里看&#xff0c;它背后玄机很多。许多未知理论与认知可能性&#xff0c;往往就在不为人知的拐角处。卞之琳有一首诗&#xff1a;你站在桥上看风景&#xff0c;看风景的人在楼上看你。明月装饰了你的窗子&#xff0c;你装饰了别人的梦。…

华为鸿蒙系统正式拜拜,从“哄蒙”到“鸿蒙”,现在,正式对华为鸿蒙OS说你好!...

从鸿蒙发布之初一直到现在&#xff0c;很多网友都为鸿蒙出谋划策&#xff0c;毕竟是我们自己的系统&#xff0c;而现在也确实需要一套自研的、成熟的智能操作系统了。再加上鸿蒙万物互联的这个大设想&#xff0c;大家伙确实是很兴奋&#xff0c;同时在这个时代里面&#xff0c;…

英文书《用unreal来学习c++》_用机器学习来概括《哈利波特》,四句话总结一场戏...

毒栗子 发自 凹非寺量子位 出品 | 公众号 QbitAI文章太长读不下去的时候&#xff0c;就想有个TL;DR按钮&#xff0c;用最短的时间&#xff0c;看最关键的部分。要是视频很长不想看&#xff0c;该怎么挑重点食用&#xff1f;一位叫做Sagi Shaier的程序猿&#xff0c;用机器学习给…

什么是负边沿触发_用好示波器必须学会的知识:触发方式

我们先简单回顾下什么是示波器的触发。由于信号无时无刻都在变化&#xff0c;如果一股脑的都把他们显示在示波器上&#xff0c;就会很乱&#xff0c;根本无法让我们看清楚&#xff0c;从而也就无法观察信号来解决问题。考虑到信号大多数时候都是以某种规律周期性出现的&#xf…

html placehonlder属性,HTML input placeholder 属性

HTML placeholder 属性实例 1带有 placeholder 文本的两个输入字段&#xff1a;尝试一下 placeholder 文本也可以指定颜色。实例 2带有 placeholder 文本设置颜色&#xff1a;尝试一下 浏览器支持Internet Explorer 10、Firefox、Opera、Chrome 和 Safari 支持 placeholder 属性…

python画图显示不了中文_完美解决Python matplotlib绘图时汉字显示不正常的问题

Matplotlib是一个很好的作图软件&#xff0c;但是python下默认不支持中文&#xff0c;所以需要做一些修改&#xff0c;方法如下&#xff1a; 1.在python安装目录的Lib目录下创建ch.py文件。 文件中代码为&#xff1a; 保存&#xff0c;以后通过以下代码调用&#xff1a; #-*-co…

监听一个可下拉区域的滚动监听_Flutter 实现一个悬浮的效果

知乎视频​www.zhihu.com在原来的基础布局下修改江景&#xff1a;Flutter 实现钉钉侧边栏​zhuanlan.zhihu.com修改 DTMessageScreen使用 Stack 作为容器且套 SingleChildScrollView &#xff0c;监听 controller 滚动事件再 Stack 容器中多添加一个DTMessageTopQuick&#xff…

【Hive】——函数案例

1 Hive 多字节分隔符处理 1.1 默认规则 Hive默认序列化类是LazySimpleSerDe&#xff0c;其只支持使用单字节分隔符&#xff08;char&#xff09;来加载文本数据&#xff0c;例如逗号、制表符、空格等等&#xff0c;默认的分隔符为”\001”。根据不同文件的不同分隔符&#xf…

qaxwidget传递参数到html,记一次QT使用QAxWidget打开.html文件调用显示离线百度地图不能缩放,自定义图片不能显示解决方法...

主要问题&#xff1a; 一开始用的是在线的&#xff0c;都没有什么问题&#xff0c;自定义图片均可以显示&#xff0c;可是后面试了一下离线百度地图&#xff0c;在qt中运行打开.html文件和在电脑上面直接双击打开此文件显示是有差别的&#xff0c;在qt生成的程序中&#xff0c;…