优先级队列与堆的关系

队列具有先进先出的特性,而优先级队列是按照优先级来进行处理。即:优先级队列的出队列操作不是直接将队头元素出队列,而是把队列中优先级最高的元素出队列。
要选出优先级最高的元素则可以借助堆来完成。

堆分为:最小堆和最大堆。
最小堆:
将数据按照二叉树的方式进行排列,其中每个节点的根节点的值小于其左子树和右子树,与左、右孩子的大小无关,称为最小堆。
最大堆:
将数据按照二叉树的方式进行排列,其中每个节点的根节点的值大于其左子树和右子树,与左、右孩子的大小无关,称为最大堆。
优先级队列与堆的关系_第1张图片
堆:

#include 
#include 
#include 
#include 
using namespace std;

template<class T>
struct Less
{
    bool operator()(const T& left, const T& right)
    {
        return left->_weight < right->_weight;
    }
};

template<class T>
struct Greater
{
    bool operator()(const T& left, const T& right)
    {
        return left->_weight > right->_weight;
    }
};

// 小堆
template<class T, class Compare = Less>
class Heap
{
public:
    Heap()
    {}

    Heap(const T arr[], size_t size, const T& invalid)
    {
        _heap.resize(size);
        for(size_t i=0; i//先将所有的数都放入堆中
        {
            _heap[i] = arr[i];
        }
        int root = (_heap.size()-2)>>1;//将堆中的数据向下调整
        for(; root>=0;--root)
            _AdjustDown(root);
    }
    void Insert(const T& data)
    {
        _heap.push_back(data);
        if(_heap.size() > 1)
            _AdjustUp();
    }
    void Remove()
    {
        assert(!_heap.empty());
        std::swap(_heap[0], _heap[_heap.size() - 1]);
        _heap.pop_back();
        if(_heap.size() > 1)
            _AdjustDown(0);
    }

    size_t Size()const
    {
        return _heap.size();
    }

    bool Empty()const
    {
        return 0 == _heap.size();
    }
    const T& Top()const
    {
        return _heap[0];
    }
    void _AdjustDown(size_t parent)
    {
        size_t child = parent*2+1;
        size_t size = _heap.size();
        while(child < size)
        {
            if(child+1 < size && Compare()(_heap[child+1], _heap[child]))
                child += 1;
            if(Compare()(_heap[child], _heap[parent]))
            {
                std::swap(_heap[child], _heap[parent]);
                parent = child;
                child = parent*2 + 1;
            }
            else
                return ;
        }
    }
    void _AdjustUp()
    {
        size_t child = _heap.size()-1;
        size_t parent = (child-1) >> 1;
        while(child != 0)
        {
            if(Compare()(_heap[child], _heap[parent]))
            {
                std::swap(_heap[child], _heap[parent]);
                child = parent;
                parent = (child-1) >> 1;
            }
            else
                return ;
        }
    }
private:
    std::vector _heap;
};

堆里面存在向下调整和向上调整。
向下调整:从根节点向下调整,直到第一个非叶子结点。即:孩子节点为_heap[size-1],
child_left = parent*2 + 1;
child_right = child_left;
向上调整:从最后一个叶子节点开始,向上调整直到child == 0.
若孩子节点大于双亲节点,则交换孩子节点与双亲节点的值,
然后修改孩子节点与双亲节点的位置。

优先级队列

#include "heap.h"
template<class T, class Compare = Less<T>>
class PriorityQueue
{
public:
    PriorityQueue()
    {}
    PriorityQueue(const T arr[], size_t size)
    {
        _hp = Heap<T>(arr, size);
    }
    void Push(const T& data)
    {
        _hp.Insert(data);
    }
    void Pop()
    {
        _hp.Remove();
    }
    const T& Top()const
    {
        return _hp.Top();
    }
    size_t Size()const
    {
        return _hp.Size();
    }

    bool Empty()const
    {
        return _hp.Empty();
    }

protected:
    Heap<T, Compare> _hp;
};

其实优先级队列就是将堆进行一次封装,都调用了堆的函数。

你可能感兴趣的:(数据结构)