838. 堆排序

输入一个长度为n的整数数列,从小到大输出前m小的数。

输入格式

第一行包含整数n和m。

第二行包含n个整数,表示整数数列。

输出格式

共一行,包含m个整数,表示整数数列中前m小的数。

数据范围

1mn1051≤m≤n≤105,
11091≤数列中元素≤109

输入样例:

5 3
4 5 1 3 2

输出样例:

1 2 3



#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int n,m;
int h[N];
int size;
//u表示当前元素的堆的起始位置
void down(int u){
    int t = u;//t表示三个点的最小值
    //首先判断有没有左儿子
    //判断左儿子
    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;
    
    //当u不等于t,说明u不是我们的最小值,然后把t换成最小值
    //所以需要将t和u的位置换一下,换成三个点中最小的
    if(u != t){
        //最小值和父元素交换
        swap(h[u],h[t]);
        
        //继续往下判断
        down(t);
    }
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++){
        scanf("%d",&h[i]);
    }
    
    size = n;
    //插入元素,一般的插入nlog(n),这里用折半插入
    for(int i = n/2;i;i--) down(i);//递推,错位相减,得出等比数列前n项和小于1,得出插入的复杂度为O(n)
    while(m -- ){
        printf("%d ",h[1]);
        h[1] = h[size];size --;
        
        down(1);
    }
    
    return 0;
}

  

 
posted @ 2019-10-27 10:07  香草味羊扒饭  阅读(149)  评论(0编辑  收藏  举报