堆的应用

此文章用到了之前堆的建立的代码,下面是链接 堆的建立

1.优先级队列

优先级队列 是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。

#pragma once
#include <cassert>
#include <iostream>
#include <cstdlib>
#include "Heap.h"
using namespace std;

template <class T , class Compare = Greater<T>>
class PriorityQueue
{
public:
    PriorityQueue(T* array, size_t size)
        :_h(array, size)
    {}
    void Push(const T& d)
    {
        _h.Push(d);
    }
    void Pop()
    {
        _h.Pop();
    }
    const T& Top()
    {
        return _h.GetTop();
    }
protected:
    Heap <T, Compare> _h;
};
void TestPriorityQueue()
{
    int a[] = { 3, 8, 12, 2, 19, 11, 14, 13, 15, 10 };
    PriorityQueue<int> a1(a, 10);
}

2.n个数中找出最大的前k个数

在有大量的数据时,找出最大的前k个数。此类问题可以用堆来解决。

首先,取出n个数据中的前k个数,创建一个有k个数据的小堆。
然后,把后面的数据依次和堆顶的数据比较,找出俩个数中大的数据放在堆顶,调用向下调整算法,保证这是一个小堆。这样就可以找出最大的前k个数。

找出最小的k个数的方法也类似。
注意:找最大数时建的是小堆,找最小数时建的是大堆。

#pragma once
#include <cassert>
#include <iostream>
#include <cstdlib>
using namespace std;
#define K 10
#define N 10000

template <class T>
//将根节点向下调整
void AdjustDown(T *top,int root)
{
    assert(root < K);
    size_t parent = root;
    size_t child = parent * 2 + 1;
    while (child < K)
    {
        if (child + 1 < K && top[child + 1] < top[child])
        {
            ++child;
        }
        if (top[child] < top[parent] && child < K)
        {
            swap(top[parent], top[child]);
            parent = child;
            child = parent * 2 + 1;
        }
        else
        {
            return;
        }
    }
}

template <class T>
void GetTopK(T *arr,T *top)
{
    assert(K < N);
    for (size_t i = 0; i < K; i++)//取出N个数据的前K个数
    {
        top[i] = arr[i];
    }

    for (int j = (K - 2) / 2; j >= 0; j--)//创建一个有K个数据的小堆
    {
        AdjustDown(top, j);
    }

    for (size_t i = K; i < N; i++)//比较第K+1--第N个数据,找出最大的K个数
    {
        if (arr[i] > top[0])
        {
            swap(arr[i], top[0]);
            AdjustDown(top, 0);
        }
    }
}

template <class T>
void print(T *top)
{
    for (size_t i = 0; i < K; i++)
    {
        cout << top[i] << " ";
    }
    cout << endl;
}

void TestGetTopK()
{
    int arr[N] = { 0 };
    int top[K] = { 0 };
    for (size_t i = 0; i < N; i++)
    {
        arr[i] = i;
    }
    GetTopK(arr, top);
    print(top);
}

3.堆排序

以升序为例,堆排序首先建一个小堆,找到最小的数据,放到最后。通过向下调整算法(此时不用管数组的最后一个元素),找到最小的数据,放到最后,这样依次操作,可把数组排序。

如图,一个数组a
这里写图片描述

建成小堆为
这里写图片描述

交换堆顶与最后的数据
这里写图片描述

数组调整为
这里写图片描述
最小的数调整到后

代码:

#pragma once
#include <cassert>
#include <iostream>
#include <cstdlib>
using namespace std;

template <class T>
void Adjustdown(T* arr ,size_t root,size_t size)
{
    size_t parent = root;
    size_t child = parent * 2 + 1;
    while (parent < size)
    {
        if (arr[child] > arr[child + 1] && child + 1 < size)
        {
            ++child;
        }
        if (arr[child] < arr[parent] && child < size)
        {
            swap(arr[child], arr[parent]);
            parent = child;
            child = parent * 2 + 1;
        }
        else
        {
            break;
        }
    }
}

template <class T>
void HeapSort(T* arr, size_t size)
{
    assert(arr);
    for (int i = (size - 2) / 2; i >= 0; i--) //建小堆
    {
        Adjustdown(arr, i, size);
    }
    size_t end = size - 1;
    while (end > 0)
    {
        swap(arr[0], arr[end]);
        Adjustdown(arr, 0, end);
        end--;
    }
};
template<class T>
void print(T* arr,size_t size)
{
    for (int i = 0; i < size; i++)
    {
        cout << arr[i] << "  ";
    }
    cout << endl;
}
void TestHeapSort()
{
    int a[] = {7,1,0,5,8,2};
    HeapSort(a, sizeof(a)/sizeof(a[0]));
    print(a, sizeof(a) / sizeof(a[0]));
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值