堆排

从大到小排序。建立一个大顶堆。每次交换(a[0], a[n-1])。并且n--。那么剩下的数继续重建大顶堆就可以了。
下次交换(a[0],a[n-2]),...,(a[0],a[1])。那么堆排就完成了。

堆排序是一种选择排序,整体主要由构建初始堆+交换堆顶元素和末尾元素并重建堆两部分组成。其中构建初始堆经推导复杂度为O(n),在交换并重建堆的过程中,需交换n-1次,而重建堆的过程中,根据完全二叉树的性质,[log2(n-1),log2(n-2)...1]逐步递减,近似为nlogn。所以堆排序时间复杂度一般认为就是O(nlogn)级。

建堆的复杂度:

#include<bits/stdc++.h>
using namespace std;

int a[100005];

struct Sort{
    void sort(int a[], int len){
        if(len<=1) return ;
        for(int i=len/2-1; i>=0; i--){//建立大顶堆
            heapify(a, i, len);
        }
        for(int i=len-1; i>0; i--){//交换+重建
            swap(a[i], a[0]);
            len--;
            heapify(a, 0, len);
        }
    }
    void heapify(int a[], int i, int len){
        int pl=i*2+1, pr=i*2+2, mxi=i;
        if(pl<len&&a[pl]>a[mxi]){
            mxi=pl;
        }
        if(pr<len&&a[pr]>a[mxi]){
            mxi=pr;
        }
        if(mxi!=i){
            swap(a[i], a[mxi]);
            heapify(a, mxi, len);
        }
    }
}T;

int main() {

    int n; scanf("%d", &n);
    for(int i=0; i<n; i++) scanf("%d", &a[i]);
    T.sort(a, n);
    for(int i=0; i<n; i++){
        printf("%d\n", a[i]);
    }

    return 0;
}
/*
8
7 8 1 6 3 74 6 4 5
*/
posted @ 2021-02-23 23:53  liweihang  阅读(124)  评论(0编辑  收藏  举报
Live2D