acwing 838. 堆排序-java版本
题目所属分类
堆是一个完全二叉树 最后一层结点是从左到右排布的
把数组建成堆 O(n)的时间复杂度
为啥从下到上遍历:如果从上往下遍历,当某个节点即是父节点又是子节点并且它的子节点仍然有子节点的时候,因为子节点还没有遍历到,所有子节点不符合小根堆的性质,当子节点调整的时候,必然会影响父节点的二次调整。
数据结构中的堆 y总的经典模板
// h[N]存储堆中的值, h[1]是堆顶,x的左儿子是2x, 右儿子是2x + 1
// ph[k]存储第k个插入的点在堆中的位置
// hp[k]存储堆中下标是k的点是第几个插入的
int h[N], ph[N], hp[N], size;
// 交换两个点,及其映射关系
void heap_swap(int a, int b)
{
swap(ph[hp[a]],ph[hp[b]]);
swap(hp[a], hp[b]);
swap(h[a], h[b]);
}
void down(int u)
{
int t = u;
if (u * 2 <= size && h[u * 2] < h[t]) t = u * 2;
if (u * 2 + 1 <= size && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
if (u != t)
{
heap_swap(u, t);
down(t);
}
}
void up(int u)
{
while (u / 2 && h[u] < h[u / 2])
{
heap_swap(u, u / 2);
u >>= 1;
}
}
// O(n)建堆
for (int i = n / 2; i; i -- ) down(i);
作者:yxc
链接:https://www.acwing.com/blog/content/404/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
原题链接
题解
import java.util.Scanner;
public class Main{
static int N = 100010;
static int[] h = new int[N];
static int size;
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int m = scan.nextInt();
for(int i = 1 ; i <= n ; i++ ) h[i] = scan.nextInt();
size = n ;
//从n/2的位置开始将数组中的值插入堆中
//堆结构是一个完全二叉树,所有有分支的数等于没有分支的数,即最后一排的数量等于上面所有的数
//最下面一排没有分支的数不用参与插入,所以从n/2开始进行插入
for(int i = n / 2 ; i >= 0 ;i--){//把数组转换成堆
down(i);//就是让他进行向下排序处理
}
while(m -- > 0){
//输出前m小的m个元素
System.out.print(h[1] + " "); //每一次输出头节点
//因为是数组,删除第一个数复杂,删除最后一个元素比较简单
//所以就将最后一个元素将第一个元素覆盖掉,然后删除掉最后一个元素
h[1] = h[size--];
//然后进行堆排序,对第一个元素进行处理
down(1);
}
}
//交换函数
public static void swap(int x,int y){
int temp = h[x];
h[x] = h[y];
h[y] = temp;
}
//堆函数核心函数,堆排序函数,传入的参数u是下标
public static void down(int u){
int t = u; // t用来分身变量
//u的左分支下标小于size说明该数存在,然后如果这个数小于t,则让左下标赋值给t,即u的分身
if(u * 2 <= size && h[u * 2] < h[t]) t = u * 2;
//u的右分支下标小于size说明该数存在,然后如果这个数小于t,因为可能上面的if语句会重置t,则判断是不是小于新或旧t,
//如果小于t的话,就让右下标赋值给t ,即u的分身。
if(u * 2 + 1 <= size && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
//如果u不等于t,说明左或者右下标有比较小的值赋值给t了,分身变了
if(u != t){
//就让u跟t这两个数交换一下位置,让小的数替代u的位置
swap(u,t);
//然后继续递归t下标小的位置
down(t);
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)