服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C语言堆结构处理TopK问题详解

C语言堆结构处理TopK问题详解

2023-02-09 15:47配的上了吗 C/C++

TopK问题即在N个数中找出最大的前K个,这篇文章将详细讲解如何利用小根堆的方法解决TopK问题,文中代码具有一定参考价值,快跟随小编一起学习一下吧

问题

在一百万个数据中,求出最大的k个数字,怎么效率高。

1. 将一百万个数据排序,承接上一篇的堆排序,时间复杂度为O(N * LogN)。但是显然这并不是最优解。

2. 一百万个数据放入一个数组中,将其视为一个完全二叉树,并用向下调整算法将其调整为一个大堆/小堆,然后Top/Popk次,即可求出前K个最大/最小的数字,时间复杂度为:O(N + K*LogN)

3. 用正确的堆处理TopK算法: 先假设求最大的K个数字,则建立大小为K的小根堆,然后在一百万-k个数据中,逐个遍历,若某个数据比小根堆的堆顶元素大,则替换掉堆顶元素,然后向下调整,使得这个堆重新变回一个小根堆。 时间复杂度为:O(K + (N-k)*LogK)

其实相较于2,3并没有时间上的很大提升,但是3在空间复杂度上有了巨大提升,2的空间为O(N),3为O(K)。 折中思考,3方法是求数据量较大的数据集合中前K个最大值/最小值的最佳方法

分析

求K个最大值,建小堆,是因为,若遍历途中遇到了那K个数中的某一个,他一定比堆顶元素大,然后替换进去之后,向下调整,可以使得这个数字置于这个小根堆的底部。从而达到目的。

代码实现

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void AdjustUp(int* a, int child)
{
    int parent = (child - 1) / 2;
    while (child > 0)
    {
        if (a[child] > a[parent])
        {
            swap(a[parent], a[child]);
            child = parent;
            parent = (child - 1) / 2;
        }
        else
        {
            break;
        }
    }
}
void AdjustDown(int* a,int size, int parent) // size 是总大小,parent是从哪里开始向下调整
{
    int child = parent * 2 + 1;
    while (child < size)
    {
        if (child + 1 < size && a[child + 1] > a[child])
            child++;
        if (a[child] > a[parent])
        {
            swap(a[child], a[parent]);
            parent = child;
            child = parent * 2 + 1;
        }
        else
        {
            break;
        }
    }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
void Print_Heap_Topk(int* a, int n, int k)
{
    int* KMaxHeap = new int[k];   // 最大堆存最小的K个数
    for (int i = 0; i < k; ++i)
    {
        KMaxHeap[i] = a[i];
    }
    for (int i = (k - 1 - 1) / 2; i >= 0; --i)
    {
        AdjustDown(KMaxHeap, k, i);
    }
    for (int i = k; i < n; ++i)
    {
        if (a[i] < KMaxHeap[0])
            KMaxHeap[0] = a[i];
        AdjustDown(KMaxHeap, k, 0);
    }
    for (int i = 0; i < k; ++i)
    {
        cout << KMaxHeap[i] << " ";
    }
    cout << endl;
}
void test_topk()
{
    int n = 10000;
    int* a = new int[n];
    srand(time(0));
    for (int i = 0; i < n; ++i)
        a[i] = rand() % 1000000;
    a[5] = 1000000 + 1;
    a[1231] = 1000000 + 2;
    a[531] = 1000000 + 3;
    a[5121] = 1000000 + 4;
    a[120] = 1000000 + 5;
    a[99] = 1000000 + 6;
    a[0] = 1000000 + 7;
    a[76] = 1000000 + 8;
    a[423] = 1000000 + 9;
    a[3144] = 1000000 + 10;
    a[333] = -100;
    a[999] = -200;
    a[777] = -500;
    a[888] = -800;
    a[111] = -1000;
    a[798] = -1;
    a[1111] = -250;
    a[2222] = -350;
    a[3333] = -450;
    a[4444] = -550;
    Print_Heap_Topk(a, n, 10);
}
int main()
{
    test_topk();
    return 0;
}

到此这篇关于C语言堆结构处理TopK问题详解的文章就介绍到这了,更多相关C语言TopK问题内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/i777777777777777/article/details/125034312

延伸 · 阅读

精彩推荐
  • C/C++纯C语言:递归最大数源码分享

    纯C语言:递归最大数源码分享

    这篇文章主要介绍了纯C语言:递归最大数源码,需要的朋友可以参考一下...

    C语言教程网4332021-01-13
  • C/C++C++调用C接口的实现示例

    C++调用C接口的实现示例

    这篇文章主要介绍了C++调用C接口的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着...

    DeRoy3902021-10-08
  • C/C++模拟实现C语言中的内存管理

    模拟实现C语言中的内存管理

    这篇文章主要内容是模拟C语言中的内存管理,需要的朋友可以参考下...

    -FIGHTING-11802021-03-04
  • C/C++C语言指针基础详解

    C语言指针基础详解

    这篇文章主要介绍了C语言指针的基础,主要对C语言中指针的本质及常见用法做了较为通俗易懂的分析,是后续深入学习C语言的基础,需要的朋友可以参考下...

    RookieStriver5292022-02-12
  • C/C++C语言实现推箱子游戏的代码示例

    C语言实现推箱子游戏的代码示例

    这篇文章主要介绍了C语言实现推箱子游戏的代码示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们...

    ZackSock5902021-08-03
  • C/C++C/C++程序开发中实现信息隐藏的三种类型

    C/C++程序开发中实现信息隐藏的三种类型

    这篇文章主要介绍了C/C++程序开发中实现信息隐藏的三种类型的相关资料,需要的朋友可以参考下...

    smstong4992021-03-25
  • C/C++C++ 中strcpy标准写法实例详解

    C++ 中strcpy标准写法实例详解

    这篇文章主要介绍了C++ 中strcpy标准写法实例详解的相关资料,需要的朋友可以参考下...

    avril10842021-05-17
  • C/C++C语言中main函数与命令行参数详细讲解

    C语言中main函数与命令行参数详细讲解

    这篇文章主要为大家详细介绍了C语言main()函数与命令行参数问题,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,...

    清风自在 流水潺潺11532022-11-10