您的位置:首页 > 其它

堆排序

2015-06-18 17:32 295 查看
最近准备面试,堆排序进行复习一下。

堆排序,主要用到了数据结构中的堆。对于堆,我们定义为一棵二叉树的孩子结点都小于等于(或大于等于)其双亲结点的二叉树。

node(i) >= node(i * 2) && node(i) >= node(i * 2 + 1),这是最大堆。

node(i) <= node(i * 2) && node(i) <= node(i * 2 + 1),这是最小堆。

堆排序的思想:

1,首先建立一个最大堆(或者最小堆[排出的顺序不同而已])

2,取出堆顶元素,然后,把最后元素放到堆顶,再次调整为整堆。

3,重复2,直到最后为有序。

堆排序主要需要解决的问题就两个:

1,如何将无序的序列调整为堆, 也就是如何舰堆?

2,如何在输出对顶,把最后一个元素放到堆顶后,再次调整为堆。

先解决第二个问题?

这个问题特别简单,在把最后一个元素放到堆顶后,我们需要把当前堆顶元素进行调整,再次调整为堆就好。具体做法为,将堆顶的元素移到其较小(值交小) 孩子的位置,然后再调整该元素(最初为堆顶的元素),以此类推。 我们称这个操作为筛选

第一个问题的话。

我们只需要以第一个非叶子节点开始进行筛选。开始建堆。

为什么要以第一个非叶子节点开始呢?

Code:

Solution{
public:
    //筛选的过程
    void heapAdjust(int *a, int s, int m)
    {
        for(int i = 2 * s; i <= m; i = i * 2){
            if(i < m && a[i + 1] > a[i]) ++ i;
            if(a[i] <= a[s]) break;
            swap(a[i], a[s]); s = i;
        }
    }

    void heap_sort(int *a, int n)
    {
        for(int i = n / 2; i >= 0; -- i){ // 建堆的过程
            heapAdjust(a, i, n - 1);
        }

        for(int i = n - 1; i >= 0;  -- i){
            swap(a[0], a[i]);
            heapAdjust(a, 0, i - 1);
        }
    }
};


代码还是比较简单的。那么,我们来分析一下堆排序的时间复杂度。

我们在建堆的时候时间复杂度为O(n),那么我在筛选的时候的时间复杂度为O(logn)。

至于建堆的时间复杂度的证明,比较麻烦。

最优情况下,最坏,平均复杂度都为O(nlogn)。

堆排序就先学习到这里。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: