数据结构+算法-堆排序
堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
以最小堆为例
下沉操作
对于一个非叶子节点的下沉操作指的是:如果父节点大于子节点的任何一个节点,那么父节点就要和子节点中的最小的节点交换。
代码描述
/**
* 下沉操作,构造小顶堆
* @param heap 元素数组
* @param k 当前元素下标
* @param n 数组长度
*/
public void sink(int[] heap,int k,int n) {
while (k<<1 <= n) {
int j = k<<1;
/**
* 判断左子树大还是右子树大,(当然了,对于小顶堆来说,j指向较小的那个元素)
*/
if (j < n && compare(heap,j, j+1))
j++;
/**
* 判断父节点是否大于最小的子节点,如果如果是则交换,不是则返回
*/
if (!compare(heap,k, j))
break;
exchange(heap,k, j);
k = j;
}
}
排序过程
排序的第一步是对整个无序数组进行整理使其满足二叉堆的性质,这样才能对其进行排序(对于非叶子节点所有的父节点均大于其子节点)。
然后对整个堆进行排序,过程描述如下:
对于小顶堆来说,根节点就是堆中最小的元素,把根节点(数组第一个元素)与数组最后一个元素交换,此时堆元素的长度-1
交换以后的数组可能不满足堆的性质,则以根节点开始进行下沉操作,直到数组满足堆得性质。
然后继续交换第一个节点与最后一个节点,如此反复,直到数组中只有一个节点,排序结束
代码描述
/**
* 排序
* 首先对一个无序的数组进行下沉操作,以至于满足堆的性质,(所有的父节点均大于其子节点)
* 然后对整个堆进行排序
* @param heap
*/
public void sort(int[] heap) {
int n = heap.length-1;
/**
* 第一个for循环用户构造一个满足堆特点的二叉堆
* 对所有的非叶子节点执行下沉操作
*/
for (int k = n>>1; k >= 1; k--)
sink(heap, k, n);
/**
* 对二叉堆进行堆排序
* 对于小顶堆来说,根节点就是堆中最小的元素,把根节点(数组第一个元素)与数组最后一个元素交换,此时堆元素的长度-1
* 交换以后的数组可能不满足堆的性质,则以根节点开始进行下沉操作,直到数组满足堆得性质。
* 然后继续交换第一个节点与最后一个节点,如此反复,直到数组中只有一个节点,排序结束
*/
while (n > 1) {
exchange(heap, 1, n--);
sink(heap, 1, n);
}
}
完整代码:
package club.test;
import org.junit.Test;
/**
* 堆排序(小顶堆为例)
* @author jiajia
*
*/
public class TestMain8 {
@Test
public void test() {
int[] a=new int[] {0,2,8,5,3,6};
sort(a);
for(int i=0;i<a.length;i++) {
System.out.print(a[i]+" ");
}
}
/**
* 排序
* 首先对一个无序的数组进行下沉操作,以至于满足堆的性质,(所有的父节点均大于其子节点)
* 然后对整个堆进行排序
* @param heap
*/
public void sort(int[] heap) {
int n = heap.length-1;
/**
* 第一个for循环用户构造一个满足堆特点的二叉堆
* 对所有的非叶子节点执行下沉操作
*/
for (int k = n>>1; k >= 1; k--)
sink(heap, k, n);
/**
* 对二叉堆进行堆排序
* 对于小顶堆来说,根节点就是堆中最小的元素,把根节点(数组第一个元素)与数组最后一个元素交换,此时堆元素的长度-1
* 交换以后的数组可能不满足堆的性质,则以根节点开始进行下沉操作,直到数组满足堆得性质。
* 然后继续交换第一个节点与最后一个节点,如此反复,直到数组中只有一个节点,排序结束
*/
while (n > 1) {
exchange(heap, 1, n--);
sink(heap, 1, n);
}
}
/**
* 交换元素
* @param heap
* @param i
* @param j
*/
public void exchange(int[] heap,int i,int j) {
heap[i]=heap[i]+heap[j];
heap[j]=heap[i]-heap[j];
heap[i]=heap[i]-heap[j];
}
/**
* 比较
* @param heap
* @param i
* @param j
* @return
*/
public boolean compare(int[] heap,int i,int j) {
return heap[i]>heap[j]?true:false;
}
/**
* 下沉操作,构造小顶堆
* @param heap 元素数组
* @param k 当前元素下标
* @param n 数组长度
*/
public void sink(int[] heap,int k,int n) {
while (k<<1 <= n) {
int j = k<<1;
/**
* 判断左子树大还是右子树大,(当然了,对于小顶堆来说,j指向较小的那个元素)
*/
if (j < n && compare(heap,j, j+1))
j++;
/**
* 判断父节点是否大于最小的子节点,如果如果是则交换,不是则返回
*/
if (!compare(heap,k, j))
break;
exchange(heap,k, j);
k = j;
}
}
}
评论区
请写下您的评论...
猜你喜欢
blog
插入排序 - 数据结构与算法
数据结构与算法
1412
算法思想:把所有需要排序的数据分成两个集合,一个是待排序集合,一个是已排序的集合,算法每次从未排序集合顺序或随机拿取一个数据,把它加入到已排序集合使其有序,直到未排序集合中的数据被取走完,算法结束
blog
归并排序(递归)- 数据结构与算法
数据结构与算法
1514
序,若数组只有一个元素则无需操作。每次递归结束时,左右两个数组都是有序的,然后对这两个中的数据进行排序,使整个数组有序。直到算法结束。publicclassTest8{ publicstaticint
blog
希尔排序 - 数据结构与算法
数据结构与算法
1526
算法思想:希尔排序是插入排序的增强版,其主要的算法思想还是插入排序的思想。算法描述:在插入排序的基础上,对待排序数组进行间隔为inc的分组,然后对每个分组进行直接插入排序,一次排序完成后,减小inc
blog
快速排序 - 数据结构与算法
数据结构与算法
1716
算法思想将待排序集合以该集合中随机的一个数为分界点分成左右两个集合,一次排序使其右边的集合的数据全部大于左边的集合,然后再分别递归式的对左右两个集合执行上述排序操作,直到递归集合没有数据,递归结束完
blog
选择排序 - 数据结构和算法
数据结构与算法
1488
算法思想:对冒泡排序的一种改进,每次从没有排序的集合a中拿取一个最大或最小的元素,放入有序的集合b中,直到a集合中的元素被取完算法描述:用变量i遍历整个数组,用变量j遍历i后面的数组,每次遍历i初始
数据结构与算法
1993
算法思想把所有需要排序的数据分成两个集合,一个是待排序集合,一个是已排序的集合,算法每次从未排序集合顺序或随机拿取一个数据,把它加入到已排序集合使其有序,直到未排序集合中的数据被取走完,算法结束案例
blog
冒泡排序 - 数据结构与算法
数据结构与算法
1334
算法思想:每次从没有排序的集合a中拿取一个最大或最小的元素,放入有序的集合b中,直到a集合中的元素被取完算法描述:用变量i遍历整个数组,用变量j遍历i后面的数组,每次交换i比j大的元素,使得i遍历过
blog
程序员必须掌握的数据结构和算法
数据结构与算法
2171
原文链接:https://www.zhihu.com/question/23148377?sort=created算法基础 时间复杂度 空间复杂度基础数据结构 线性表 列表(必学) 链表(必学
最新发表
归档
2018-11
12
2018-12
33
2019-01
28
2019-02
28
2019-03
32
2019-04
27
2019-05
33
2019-06
6
2019-07
12
2019-08
12
2019-09
21
2019-10
8
2019-11
15
2019-12
25
2020-01
9
2020-02
5
2020-03
16
2020-04
4
2020-06
1
2020-07
7
2020-08
13
2020-09
9
2020-10
5
2020-12
3
2021-01
1
2021-02
5
2021-03
7
2021-04
4
2021-05
4
2021-06
1
2021-07
7
2021-08
2
2021-09
8
2021-10
9
2021-11
16
2021-12
14
2022-01
7
2022-05
1
2022-08
3
2022-09
2
2022-10
2
2022-12
5
2023-01
3
2023-02
1
2023-03
4
2023-04
2
2023-06
3
2023-07
4
2023-08
1
2023-10
1
2024-02
1
2024-03
1
2024-04
1
2024-08
1
标签
算法基础
linux
前端
c++
数据结构
框架
数据库
计算机基础
储备知识
java基础
ASM
其他
深入理解java虚拟机
nginx
git
消息中间件
搜索
maven
redis
docker
dubbo
vue
导入导出
软件使用
idea插件
协议
无聊的知识
jenkins
springboot
mqtt协议
keepalived
minio
mysql
ensp
网络基础
xxl-job
rabbitmq
haproxy
srs
音视频
webrtc
javascript
加密算法
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。