堆排——杨子曰算法

堆排序——杨子曰算法

没错,它又是一个n log n的算法,有人说:学这么多排序有什么卵用?
杨子曰:装逼


堆排是用一个堆来实现的(废话)
我们这里说的堆是小根堆——就是爸爸比儿子要小的堆(听上去好别扭)
堆排的实现要分为两个部分:建堆和拆堆
我们用3,4,6,1,5,2来模拟一下
黑喂狗:


1.建堆
我们在建堆是一定要维护爸爸比儿子小,具体怎么实现呢?拿到一个数后不管三七二十一先把它放到堆底,然后和他的父亲进行比较,如果比他的父亲小,就交换,直到到顶了或者比父亲大了就停止(专业人士称之为上浮),我们用3,4,6,1,5,2来模拟一下
先把3扔进去
这里写图片描述
然后把4放到堆底
这里写图片描述
发现小根堆很和谐
继续
这里写图片描述
依然很和谐,再继续
这里写图片描述
惊悚的发现刚刚放进去的1比他爸爸小了,So我们交换
这里写图片描述
哦,依然比他爸爸小,再交换
这里写图片描述
嗯,Great,我们的小根堆依然和谐
然后就可以把5扔进去了
这里写图片描述
嗯,不用交换,继续
这里写图片描述
发现2比爸爸6小了,So上浮
这里写图片描述
OK,这下彻底和谐了,整棵堆也被我们建完了╰(๑◕ ▽ ◕๑)╯


2.拆堆
顾名思义我们要把刚才建的堆拆掉(好心痛)——拆完以后我们的数组就排好了
具体实现:
每次弹出堆顶元素,然后把堆底元素放到堆顶,然后这将这个元素与它较小的儿子不断交换(在维护小根堆),一直到底(专业人士称之为下沉)我们还是用刚才的例子:
这里写图片描述
首先弹出堆顶元素1
这里写图片描述
把堆底元素6放到对顶
这里写图片描述
然后你就会发现小根堆不和谐了,我们把6下沉,与儿子中较小的2交换
这里写图片描述
嗯,小根堆维护好了,然后继续弹出2
这里写图片描述
把堆底元素5放到对顶
这里写图片描述
开始下沉,3较小,交换
这里写图片描述
继续下沉
这里写图片描述
弹出3
这里写图片描述
把5移上来
这里写图片描述
下沉
这里写图片描述
弹出4
这里写图片描述
把6移上来
这里写图片描述
下沉
这里写图片描述
弹出5
这里写图片描述
把6移上来
这里写图片描述
弹出6
这里写图片描述
惊奇的发现我们已经排完了!


总结一波:其实堆排就是用堆来维护最小值,然后不停把最小值放到最前面——你可以把它理解成堆优化的选择排序,维护堆的复杂度是O(log n),排序时间复杂度O(n log n)

给第一次写堆的童鞋一个小tip:
堆可以用一个数组存下,用a[i]表示从上往下,从左往右数第i个节点,那么节点i的父亲就是i/2,节点i的两个儿子就是i*2 和 i*2+1

OK,完事


c++模板:

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

const int inf=200000000;

int n,heap[100005],x[100005];

int main(){
    int n;
    scanf("%d",&n);
    for (int i=1;i<=2*n;i++){
        heap[i]=inf;
    }
    int num=0,nod;
    for (int i=1;i<=n;i++){
        nod=++num;
        int k;
        scanf("%d",&k);
        heap[nod]=k;
        while(nod!=1&&heap[nod]<heap[nod/2] ) swap(heap[nod],heap[nod/2]),nod/=2;
    }
    int index=0;
    for (int i=1;i<=n;i++){
        x[++index]=heap[1];
        heap[1]=heap[num];
        heap[num--]=inf;
        int nod=1;
        while(heap[nod*2]<heap[nod]||heap[nod*2+1]<heap[nod]){
            if (heap[nod*2]<heap[nod*2+1]) swap(heap[nod],heap[nod*2]),nod*=2;
            else swap(heap[nod],heap[nod*2+1]),nod=nod*2+1;
        }
    }
    for (int i=1;i<=n;i++){
        cout<<x[i]<<' ';
    }
    return 0;
}

于XJ机房607

猜你喜欢

转载自blog.csdn.net/HenryYang2018/article/details/81216491
今日推荐