堆排序回顾

这东西。。。好简单的诶

不过貌似一年前的时候,还没有写博客的习惯

那就来总结一下呗

 

堆排序的好处是他一定不会退化,而快排会退化

 

首先来说大根堆

把大根堆当成一个完全二叉树(这个说法其实不准确)

对于a[i],左儿子为a[i*2]右儿子为a[i*2+1]

也就是说我们已经有一颗树了

然后我们从后往前fix每个节点

 

fix(x)就是将x放到他该在的地方

具体操作就是,将x与其两个子节点比较

如果x>他的两个节点,退出函数

如果x<他的两个节点

将x与他的两个节点中的最大的节点y调换位置,然后fix(y)

如果他的某个子节点为空,那就设这个子节点的值为-inf

 

在建好堆后,我们就可以保证堆顶元素最大了嘛

于是我们把堆顶元素放入数组,然后把堆尾元素放到堆顶,最后再fix(1)

重复这个过程直到堆中元素为0

 

代码:

这代码我一年前写的,写的好丑,请不要介意

#include <iostream>

using namespace std;

int parent(int i){return i/2;}
int left (int i) {return i*2;}
int right (int i) {return i*2+1;}
void maintenance (int *a,int i,int len);
void Swap(int &a,int &b) {int s;s=a;a=b;b=s;return;}
void in(int *a,int &l);
void build(int *a,int l);
void heap_sort(int *a,int l);

int main()
{
    int a[5000],l;
    in(a,l);
    build(a,l);
    heap_sort(a,l);
    for (int k=1;k<=l;k++)
        cout<<a[k]<<" ";
    return 0;
}

void in (int *a,int &l)
{
    int i=1;
    while (cin>>a[i]) i++;
    l=i-1;
    return;
}

void maintenance (int *a,int i,int len)
{
    int l=left(i),r=right(i),large=0;
    if (l<=len&&a[i]<a[l]) large=l;
    else large=i;
    if (r<=len&&a[large]<a[r]) large=r;
    if (large==i) return;
    Swap(a[i],a[large]);
    maintenance(a,large,len);
    return;
}

void build (int *a,int l)
{
    for (int k=l/2;k>=1;k--)
        maintenance(a,k,l);
    return;
}

void heap_sort(int *a,int l)
{
    for (int k=l;k>=1;k--)
    {
        Swap(a[1],a[k]);
        l--;
        maintenance(a,1,l);
    }
    return;
}

 

posted @ 2017-12-24 22:39  shensobaolibin  阅读(254)  评论(0编辑  收藏  举报