面试题:利用堆排序实现从n个数字中找出前top-k大的数字

用堆排序(最小堆):top-k最大的数字


题目:top-k算法,从n个大小的数组中,找出k个最大的数字并输出

输入:数组大小n=10;k的值为5;数组为:9,8,3,2,10,20,13,1,5

输出:20,13,10,9,8

思路:1、维护k个最小堆,如果某个新进来的数字大于最小堆的根节点,那么将根节点换为新进来的数字,然后在对最小堆进行调整。
2、在找出k个大的数字后,对k个大的数字进行一次堆排序,因为我们做的是最小堆,所以堆排序后得到的序列就是升序的序列
Ps:堆排序的平均时间复杂度都为O(n*logn),它比快排好的地方是,快排在最坏的情况下(数组已有序)时间复杂度为O(n^2)

/*
题目:堆排序的用法:
      1、利用堆排序从n个数字中取出top-k个最大的数字
      2、主要使用最小堆,维护k个大小的最小堆
*/
#include<iostream>
#include<vector>
using namespace std;

void headAdjust(vector<int> &arr, int start, int end){
    int temp = arr[start];
    //i这里指向的是左子树
    int i = start * 2 + 1;
    while (i <= end){
        //先找左右子树中最小的
        if (i + 1 <= end&&arr[i] > arr[i + 1]){
            //如果左子树大于右子树,则i指向右子树
            i++;
        }
        if (temp > arr[i]){
            arr[start] = arr[i];
            start = i;
            i = 2 * start + 1;
        }
        else{
            break;
        }
    }
    arr[start] = temp;
}

void heapSort(vector<int> &arr, int start, int end){
    //堆排序是从第一个非叶节点开始从下往上更新,直到更新到根节点为止
    for (int i = end / 2 - 1; i >= 0; i--){
        headAdjust(arr,i,end);
    }
    //下面进行堆排序
    for (int i = end; i-1 >= 0; i--){
        int temp = arr[i];
        arr[i] = arr[0];
        arr[0] = temp;
        headAdjust(arr, 0, i-1);
    }
}

int main(){
    //堆排序维护k个大小的最小堆
    int k;
    int n;
    cin >> n;
    cout << "top-k的值为:";
    cin >> k;
    cout << "依次输入数组,然后找出top-" << k << "个值" << endl;
    vector<int> arr(k,0);
    for (int i = 0; i < n; i++){
        if (i > k - 1){
            int temp;
            cin >> temp;
            if (temp > arr[0]){
                arr[0] = temp;
                headAdjust(arr, 0, k - 1);
            }
        }
        else{
            int temp;
            cin >> temp;
            arr[i] = temp;
            if (i == k - 1){
                headAdjust(arr, 0, k - 1);
            }
        }
    }
    //对堆进行最小堆排序
    heapSort(arr, 0, k - 1);
    for (int i = 0; i < arr.size(); i++){
        cout << arr[i];
        if (i < arr.size()-1){
            cout << " ";
        }
    }
    system("pause");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_37885286/article/details/80104774