美文网首页
堆的应用

堆的应用

作者: 修夏之夏i | 来源:发表于2018-08-29 16:51 被阅读0次
堆排序
100个亿数中找出最小的前k个数(海量数据 Top k 问题)-->建大堆
100个亿数中找出最大的前k个数(海量数据 Top k 问题)-->建小堆

Heap.h

#define _CRT_SECURE_N0_WARNINGS 1

#include <stdio.h>
#include <assert.h>

typedef struct Heap{
    int array[100];
    int size;
}Heap;

static void Swap(int *a, int *b)
{
    int t = *a;
    *a = *b;
    *b = t;
}

//初始化
void HeapInit(Heap *pH, int source[], int size)
{
    for (int i = 0; i < size; i++)
    {
        pH->array[i] = source[i];
    }
    //更改堆的实际大小
    pH->size = size;
}

void ArrayAdjustDown(int array[], int size, int root)
{
    int parent = root;

    while (1) {
        // 先判断有没有孩子(叶子结点)
        // 数组角度去想   -> 孩子的下标是否越界
        // 只要判断左孩子的下标(因为是完全二叉树)
        int left = parent * 2 + 1;
        if (left >= size) {
            // 越界,没有左孩子,也肯定没有右孩子
            return;
        }

        // 一定有左孩子
        int maxChild = left;
        if (2 * parent + 2 < size && array[2 * parent + 2] > array[left]) {
            // 前一个条件是判断右孩子有没有
            // 后一个条件判读是右孩子是否比左孩子大
            maxChild = 2 * parent + 2;
        }

        if (array[parent] > array[maxChild]) {
            return;
        }

        // 交换 root 和 maxChild 下标所在的值
        int t = array[parent];
        array[parent] = array[maxChild];
        array[maxChild] = t;

        parent = maxChild;
    }
}

void HeapSort(int array[], int size)
{
    for (int i = (size - 2) / 2; i >= 0; i--)
        ArrayAdjustDown(array, size, i);

    for (int j = 0; j < size; j++)
    {
        int s = size - 1 - j;
        Swap(array, array + s);
        ArrayAdjustDown(array, size - 1 - j, 0);
    }
}

void TestSort()
{
    int array[] = { 1, 4, 9, 4, 2, 7, 8, 5, 3, 6, 2, 2, 3 };
    int size = sizeof(array) / sizeof(int);

    HeapSort(array, size);

    printf("成功\n");
}


#include <stdlib.h>

// TopK 找最小的 k 个数据,需要建大堆
// 和排序不太一样:排序是在原数组调整。TopK 最好不要在原数组上调整
int * TopK(int array[], int size, int k)
{
    int *heapArray = (int *)malloc(k * sizeof(int));
    assert(heapArray);

    // 搬 前 k 个数过去
    for (int i = 0; i < k; i++) {
        heapArray[i] = array[i];
    }

    // 建堆,建大堆
    // 这里的 size 其实是 k
    for (int j = (k - 2) / 2; j >= 0; j--) {
        ArrayAdjustDown(heapArray, k, j);
    }

    for (int m = k; m < size; m++) {
        if (array[m] >= heapArray[0]) {
            continue;
        }

        heapArray[0] = array[m];
        ArrayAdjustDown(heapArray, k, 0);
        // 不要用  Swap(heapArray, array + m);
    }

    return heapArray;
}

void TestTopK()
{
    int array[] = { 1, 4, 9, 4, 2, 7, 8, 5, 3, 6, 2, 2, 3 };
    int size = sizeof(array) / sizeof(int);

    int *r = TopK(array, size, 3);

    printf("成功\n");
}

Main.c

#define _CRT_SECURE_N0_WARNINGS 1

#include "Heap.h"

int main()
{ 
    TestSort();
    TestTopK();
    return 0;
}

相关文章

  • 堆 - 堆的应用

    堆有三个典型的应用场景:实现优先队列、求 Top K 、求中位数 实现优先队列 优先队列:队列的性质是先进先出,但...

  • 堆的应用

    堆排序 100个亿数中找出最小的前k个数(海量数据 Top k 问题)-->建大堆 100个亿数中找出最大的前k个...

  • 堆的应用

    1. 堆的应用一:优先级队列 优先级队列,顾名思义,它首先应该是一个队列。队列最大的特性就是先进先出,而在优先级队...

  • 堆的应用

    堆的应用一:优先级队列 将优先级的之分的数据存入堆中(小顶堆或者大顶堆),堆顶即优先级最搞的数据,当需要的时候直接...

  • 堆的应用

    堆的应用一:优先级队列 优先级队列,顾名思义,它首先应该是一个队列。队列最大的特性就是先进先出。不过,在优先级队列...

  • 堆结构的应用

    1.随时找到数据流的中位数 【题目】有一个源源不断地吐出整数的数据流,假设你有足够的空间来保存吐出的数。请设计一个...

  • 堆及其应用

    理解堆 堆,言简意赅,是一种数据结构,它是一种特殊的树,满足以下两点: 1:堆是一钟完全二叉树; 2:堆中的每一个...

  • 图解堆结构、堆排序及堆的应用

    前言 上一次我们介绍了选择类排序中的简单选择排序,简单归简单,但是时间复杂度是O(n^2),这次我们介绍另一种时间...

  • 小根堆的应用2

    思路:小根堆的应用

  • 小根堆的应用1

    思路:利用小根堆实现

网友评论

      本文标题:堆的应用

      本文链接:https://www.haomeiwen.com/subject/ypjkwftx.html