算法复习——堆排序

堆排序主要需要先理解清楚堆(heap)。堆的定义:

对于序列{k_0, k_1,... , k_{n-1}},若满足k_i \leq k_{2i+1}, k_i \leq k_{2i+2}或者k_i \geq k_{2i+1}, k_i \geq k_{2i+2},其中i \in [0,...,floor(\frac{n}{2}-1)],则称该序列为堆。

堆可以看做是一棵二叉树。我们讨论升序排序,所以我们需要的是最大堆,也就是父节点的值总是大于等于任何一个子节点的值。

堆排序的步骤:

1) 输入乱序数组{k_0, k_1,... , k_{n-1}}

2)调整为最大堆。先调整每个非叶节点,使得该节点为根节点的子树为最大堆。

3)将根节点与最后一个节点的值互换,并将互换后的最后一个节点移出堆。

4)如果堆中的元素个数大于1,则回到2),否则,输出当前数组,则为输出排序好的数组

 

复习的时候,发现以前实现的堆排序虽然能work,但是效率有点问题。重新实现了一个版本:

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

void fixdown(vector<int> &nums, int k, int n){
    while(2*k+1 < n){
        int swap_ind = (2 * k + 2 >= n) ? 2 * k + 1:
            (nums[2*k+2] < nums[2*k+1]) ? 2*k+1: 2*k+2;
        if(nums[k] < nums[swap_ind])
            swap(nums[k], nums[swap_ind]);
        else
            break;
        k = swap_ind;
    }
}

void heapsort(vector<int> &nums){
    int n = nums.size();
    for(int i=n/2-1; i>=0; i--){
        fixdown(nums, i, n);
    }
    for(int i=0; i<n; i++){
        swap(nums[0], nums[n-i-1]);
        fixdown(nums, 0, n-i-1);
    }
}


int main(int argc, char *argv[]){
    int n;
    cin >> n;
    if(n < 2){
        cout << "Size of array must bigger than 1" << endl;
        return 0;
    }
    vector<int> array;
    for(size_t i=0; i<n; i++){
        int tmp;
        cin >> tmp;
        array.push_back(tmp);
    }

    heapsort(array);

    for(int a: array){
        cout << a << " ";
    }
    cout << endl;
    return 0;
}

 

以前实现的算法如下:

void heapsort(int *arr, int n){
    /*
        arr: array
        n: size of array
    */
    if(n == 1)
        return;
    int k, swap_ind;
    /*adjust heap*/
    for(int i=n/2-1; i>=0; i--){
        k = i;
        while(2*k+1 < n){
            swap_ind = 
                (2*k+2 >= n) ? 2*k+1 :
                (arr[2*k+1] > arr[2*k+2]) ? 2*k+1 : 2*k+2;
            if(arr[swap_ind] > arr[k]){
                swap(arr, k, swap_ind);
                k = swap_ind;
            } else {
                break;
            }
        }
    }
    //remove the top node out of heap
    swap(arr, 0, n-1);
    heapsort(arr, n-1);
}
void swap(int *arr, int i, int j){
    int tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值