求前K个最大的数(排序问题)

求前K个最大的数(排序问题)

  • 问题:g给出无序序列,求前k大(小)的数,或求第k大(小)的数。
  • 分析:
    • 1、利用快排的思想 : 快速排序每一轮其实将左右两个子序列排好序(分割点后序列中的所有数字均大于分割点前的所有数字)如果分割点是K那么很容易得到前k大(小)的数字。时间复杂o(n)
    • 2、堆排序,可以直接找到前K个最大的数即可。堆排序重要操作:1、堆调整(基于大顶堆或小顶堆调整),2、基于堆调整进行建堆 3、将对顶元素删除,并使用最后一个叶节点的元素覆盖堆顶 4、进行堆调整,5、反复进行3,、4步,直到堆中还剩k个元素。
  • 代码2(堆排序)
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
  
#include<assert.h>
  
void AdjustDown(int* a, int parent, int size)
{
    int child = 2 * parent + 1;
    while (child < size)
    {
        if (child + 1 < size && a[child] > a[child + 1])
        {
            child++;
        }
        if (a[parent]>a[child])
        {
            swap(a[parent], a[child]);
            parent = child;
            child = 2 * parent + 1;
        }
        else
        {
            break;
        }
    }
}
  
  
void Print(int* a, int size)
{
    cout << "前k个最大的数据:" << endl;
    for (int i = 0; i < size; i++)
    {
        cout << a[i] << "  ";
    }
    cout << endl;
}
  
  
int* HeapSet(int*a,int N,int K)
{
    assert(a);
    assert(K > 0);
    int* arr = new int[K];
    //将前K个数据保存
    for (int i = 0; i < K; i++)
    {
        arr[i] = a[i];
    }
  
    //建堆
    for (int i = (K-2)/2; i >=0; i--)
    {
        AdjustDown(arr,i,K);
    } 
  
    //对剩余的N-K个元素比较大小
    for (int i = K; i < N; i++)
    {
        if (arr[0]<a[i])
        {
            arr[0] = a[i];
            AdjustDown(arr, 0, K);
        }
    }
  
    return arr;
    delete[] arr;
}
  
  
void Test()
{
    int arr[] = { 12, 2, 10, 4, 6, 8, 54, 67, 25, 178 };
    int k = 5;
    int* ret = HeapSet(arr, sizeof(arr) / sizeof(arr[0]), k);
    Print(ret, k); 
}
  
  
int main()
{
    Test();
    system("pause");
    return 0;
}
  • 代码1(快排):
int Partition(vector<int> &v, int head, int rear){
    int key = v[head];
    while (head < rear){
        while (v[rear] <= key && head < rear){
            --rear;
        }
        swap(v[head], v[rear]);
        while (v[head] >= key && head < rear){
            ++head;
        }
        swap(v[rear], v[head]);

    }
    v[head] = key;
    ++my_count;
    return head;
}

int QuickSearch(vector<int> &v, int head, int rear, int k){
    int pivot = -1, len = 0;
    if (head < rear){
        pivot = Partition(v, head, rear);
        len = pivot - head + 1;
        if (len < k){
            pivot = QuickSearch(v, pivot + 1, rear, k - len);
        }
        else if (len > k){
            pivot = QuickSearch(v, head, pivot - 1, k);
        }
    }
    return pivot;
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值