堆排序
今天写的这个堆排序算法,用了很久的时间,一是理解编程思想;二是调试出现了诸多的小错误。现在记下来,下不为例。
预备知识
堆排序堆是一种特殊的树形数据结构,即完全二叉树。堆分为大根堆和小根堆,大根堆为根节点的值大于两个子节点的值;小根堆为根节点的值小于两个子节点的值,同时根节点的两个子树也分别是一个堆。
基本思路
算法实现主要分为三个步骤:
1、构造大根堆:将n个元素组成的序列构建为一个大根堆。
根据堆的树形结构,根节点的值要大于两个子节点的值,所以构建一个大根堆的子结构,就是让一个节点的左节点和右节点的值都小于该节点,如果发现左节点或者右节点的值大于该节点的值,那么执行交换操作。设一个非叶子节点的索引是index,那么左节点就是2index+1,右节点是2index+2。当不满足大根堆的子结构时,维护一个局部最大值maxindex索引,并交换到相应的位置。这时看看交换以后,符不符合大根堆的结构,不符合则从maxindex往下递归。
核心代码
private static void heapify(int[] arr, int length, int index) { int left=2*index+1; int right=2*index+2; int maxindex=index; if(left<length && arr[left] >arr[maxindex]){ maxindex=left; } if(right<length && arr[right]>arr[maxindex]){ maxindex=right; } if(maxindex!=index){ //交换arr[index]与arr[maxindex] int temp=arr[index];// arr[index]=arr[maxindex]; arr[maxindex]=temp; //递归 heapify(arr,length,maxindex); } }
2、调整大根堆:交换堆首和堆尾元素--获得最大元素
第一次heapify以后,其实已经将最大元素找出来了,最大元素位于根节点,arr[0],那么这时候将堆尾元素与堆首元素交换。
此时处于堆尾的是最大元素,最大元素将不会被改变。现在调用headify,继续构造大根堆。再取出次大的元素,置于堆尾倒数第二个位置。依次类推。
这样循环结束,也就完成了排序。
//调整大根堆 for (int i = arr.length-1; i >=0; i--) { int temp=arr[0];//交换堆首与堆尾的元素 arr[0]=arr[i]; arr[i]=temp; heapify(arr,i,0);//将未完成排序的部分,长度为i,继续进行堆排序 }
3、堆排序:
两大步骤:构造大根堆,调整大根堆。需要注意的是构建大根堆的时候首先从最后一个非叶子节点开始,然后遍历非叶子节点。i=0时,到达根节点。
//堆排序 public static void heapsort(int [] arr){ //构建大顶堆, 从最后一个非叶子节点开始 for(int i=arr.length/2-1;i>=0;i--){ heapify(arr,arr.length,i); } //调整大根堆 for (int i = arr.length-1; i >=0; i--) { int temp=arr[0];//交换堆首与堆尾的元素 arr[0]=arr[i]; arr[i]=temp; heapify(arr,i,0);//将未完成排序的部分,长度为i,继续进行堆排序 } }
图示说明:
见链接https://www.cnblogs.com/wanglei5205/p/8733524.html。
代码实现
完整代码:
public class HeapSort { //构建大根堆 private static void heapify(int[] arr, int length, int index) { int left=2*index+1; int right=2*index+2; int maxindex=index; if(left<length && arr[left] >arr[maxindex]){ maxindex=left; } if(right<length && arr[right]>arr[maxindex]){ maxindex=right; } if(maxindex!=index){ //交换arr[index]与arr[maxindex] int temp=arr[index];//交换 arr[index]=arr[maxindex]; arr[maxindex]=temp; //递归 heapify(arr,length,maxindex); } } //堆排序 public static void heapsort(int [] arr){ //构建大顶堆, 从最后一个非叶子节点开始 for(int i=arr.length/2-1;i>=0;i--){ heapify(arr,arr.length,i); } //调整大根堆 for (int i = arr.length-1; i >=0; i--) { int temp=arr[0];//交换堆首与堆尾的元素 arr[0]=arr[i]; arr[i]=temp; heapify(arr,i,0);//将未完成排序的部分,长度为i,继续进行堆排序 } } public static void main(String[] args) { int[] arr=new int[]{5,88,45,37,91,26,13,66,50}; heapsort(arr); System.out.println(Arrays.toString(arr)); } }
学习让我快乐,工作让我快乐。学习和工作都是为了更好的生活!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(三):用.NET IoT库
· 【非技术】说说2024年我都干了些啥