李林超博客
首页
归档
留言
友链
动态
关于
归档
留言
友链
动态
关于
首页
Java
正文
数据结构和算法学习--堆排序
Leefs
2020-02-14 PM
2083℃
0条
# 数据结构和算法学习--堆排序 ### 一、堆排序基本介绍 (1)堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。 (2)堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆,注意:没有要求结点的左孩子的值和右孩子的值的大小关系。 (3)每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆 (4)大顶堆举例说明 ![32.堆排序01.png][1] 我们对堆中的结点按层进行编号,映射到数组中就是下面这个样子: ![32.堆排序02.png][2] 大顶堆特点:`arr[i]>=arr[2*i+1]&&arr[i]>=arr[2*i+2]`//i对应第几个节点,i从0开始编号 (5)小顶堆举例说明 ![32.堆排序03.png][3] 小顶堆:`arr[i]<=arr[2*i+1]&&arr[i]<=arr[2*i+2]`//i对应第几个节点,i从0开始编号 (6)一般升序采用大顶堆,降序采用小顶堆 ### 二、堆排序基本思想 (1)将待排序序列构造成一个大顶堆 (2)此时,整个序列的最大值就是堆顶的根节点。 (3)将其与末尾元素进行交换,此时末尾就是最大值。 (4)然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。 可以看到在构建大顶堆的过程中,元素的个数逐渐减少,最后就得到一个有序序列了。 ### 三、堆排序步骤图解说明 > 要求:给一个数组{4,6,8,5,9}。要求使用堆排序法,将数组升序排序。 步骤一 构造初始堆,将给定无序序列构造一个大顶堆(一般升序采用大顶堆,降序采用小顶堆)。 原始的数组[4,6,8,5,9] (1).假设给定无序序列结构如下 ![32.堆排序04.png][4] (2)此时我们从最后一个非叶子结点开始(叶结点自然不用调整,第一个非叶子结点arr.length/2-1=5/2-1=1,也就是下面的6结点),从作至右,从下至上进行调整。 ![32.堆排序05.png][5] (3)找到第二个非叶子结点4,由于[4,9,8]中9元素最大,4和9交换。 ![32.堆排序06.png][6] (4)这时,交换导致了子根[4,5,6]结构混乱,继续调整,[4,5,6]中6最大,交换4和6. ![32.堆排序07.png][7] 此时,我们就将一个无序序列构造了一个大顶堆。 步骤二 将堆顶元素与末尾进行交换,使末尾元素最大。然后继续调整堆,再将堆顶元素与末尾元素交换,得到第二大元素。如此反复进行交换、重建、交换。 (1).将堆顶元素9和末尾元素4进行交换 ![32.堆排序08.png][8] (2)重新调整结构,使其继续满足堆定义 ![32.堆排序09.png][9] (3)再将堆顶元素8与末尾5进行交换,得到第二大元素8. ![32.堆排序10.png][10] (4)后续过程,继续进行调整,交换,如此反复进行,最终使得整个序列有序。 ![32.堆排序11.png][11] **思路总结** (1)将无序序列构建一个堆,根据升序降序需求选择大顶堆或小顶堆; (2)将堆顶元素与末尾元素交换,将最大元素“沉”到数组末端; (3)重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。 ### 四、堆排序代码实现 要求:给定一个数组{4,6,8,5,9},要求使用堆排序法,将数组升序排序。 **代码实现:** ```java public class HeapSort { public static void main(String[] args) { int arr[]={4,6,8,5,9}; heapSort(arr); System.out.println(Arrays.toString(arr)); } public static void heapSort(int arr[]){ int temp=0; System.out.println("堆排序!"); //将无序序列构建成一个堆,根据升序降序要求选择大顶堆或小顶堆 for(int i=arr.length/2-1;i>=0;i--){ adjustHeap(arr,i,arr.length); } /** * (2)将堆顶元素与末尾元素交换,将最大元素“沉”到数组末端; * (3)重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。 * */ for(int j=arr.length-1;j>0;j--){ //交换 temp=arr[j]; arr[j]=arr[0]; arr[0]=temp; adjustHeap(arr,0,j); } } //将一个数组(二叉树),调整成一个大顶堆 /** * 功能:完成 将 以i对应非叶子结点的树调整成大顶堆 * 举例 int arr[]={4,6,8,5,9};=>i=1=>adjustHeap=>得到{4,9,8,5,6} * 如果我们再次调用 adjustHeap 传入的是i=0 => 得到 {4,9,8,5,6}=>{9,6,8,5,4} * @param arr 待调整的数组 * @param i 表示非叶子结点在数组中索引 * @param length 表示对多少个元素继续调整,length是在逐渐减少 * */ public static void adjustHeap(int arr[],int i,int length){ int temp=arr[i];//先取出当前元素的值,保存在临时变量 //开始调整 //1.k=i*2+1 k是i节点的左子结点 for(int k=i*2+1;k
temp){//如果子结点大于父结点 arr[i]=arr[k];//把较大的值赋给当前结点 i=k;//i指向k,继续循环比较 }else{ break; } } //当for循环结束后,我们已经将以i为父结点的树的最大值,放在了最顶 arr[i]=temp;//将 temp值放到调整后的位置 } } ``` [1]: https://lilinchao.com/usr/uploads/2020/02/1485073726.png [2]: https://lilinchao.com/usr/uploads/2020/02/2598115744.png [3]: https://lilinchao.com/usr/uploads/2020/02/2685604826.png [4]: https://lilinchao.com/usr/uploads/2020/02/1433365176.png [5]: https://lilinchao.com/usr/uploads/2020/02/1289821503.png [6]: https://lilinchao.com/usr/uploads/2020/02/4161510556.png [7]: https://lilinchao.com/usr/uploads/2020/02/1237961246.png [8]: https://lilinchao.com/usr/uploads/2020/02/3202187968.png [9]: https://lilinchao.com/usr/uploads/2020/02/2143683385.png [10]: https://lilinchao.com/usr/uploads/2020/02/1505530831.png [11]: https://lilinchao.com/usr/uploads/2020/02/4035848421.png
标签:
数据结构和算法
,
排序
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:
https://lilinchao.com/archives/607.html
上一篇
HttpUtils工具类
下一篇
LeetCode-1.两数之和
评论已关闭
栏目分类
随笔
2
Java
326
大数据
229
工具
31
其它
25
GO
47
NLP
4
标签云
Hive
正则表达式
MyBatis-Plus
Http
Spark RDD
Flink
Docker
排序
Kafka
人工智能
随笔
FileBeat
国产数据库改造
JavaWeb
nginx
Yarn
算法
Redis
Ubuntu
Hbase
持有对象
MyBatisX
SQL练习题
RSA加解密
字符串
二叉树
FastDFS
数据结构和算法
Elastisearch
工具
友情链接
申请
范明明
庄严博客
Mx
陶小桃Blog
虫洞
评论已关闭