数据结构:优先队列

一般我们前面介绍的队列,队列的一个特性是先进先出。但是在作业调度的过程中我们总是希望很短的作业可以优先处理,这样我们就不用一味的等待短的作业而花费很长的时间去处理。但是同时有些短的但是很重要的作业也应该享有优先权。
优先队列至少允许以下两种操作,insert(插入)和 deleteMin(删除最小项)。insert 操作等同于 enqueue(入队),而 deleteMin 则是队列操作的 dequeue(出队)在优先级队列中的等价操作。

二叉堆实现:
我们一般称二叉堆为堆,堆有两个性质,堆序性质和结构性质。堆是一棵被完全填满的二叉树,例外在最底层,底层元素从左到右填充。这样的树被称为完全二叉树。对于数组中任意位置 i 上的元素,其左儿子在 2i 上,右儿子也就在 2i+1 上,它的父亲则则在 floor(i/2)

template <typename Comparable>
class BinaryHeap
{
    public:
        explicit BinaryHeap(int capacity = 100);
        explicit BinaryHeap(const vector<Comparable>& items);

        bool isEmpty() const;
        const Comparable& findMin() const;

        void insert(const Comparable& x);
        void deleteMin();
        void deleteMin(Comparable& minItem);
        void makeEmpty();
    private:
        int currentSize;
        vector<Comparable> array;
        void buildHeap();
        void percolateDown(int hole);
}
一个堆的数据结构将由一个数组和一个代表当前堆大小的整数组成。

堆序性质:使操作可以快速的执行的性质是堆序性质。根据堆的性质最小元总是可以在根部找到。因此实现 insert 和 deleteMin 操作是很容易的,所有的工作需要保证始终保持堆序的性质。
insert 操作:
将一个元素 X 插入到队中,我们在下一个空闲位置创建一个空穴,因为否则该堆将不是完全树。如果 X 可以放入空穴而不破坏堆序,那么插入完成。否则,把空穴的父结点上的元素移入空穴中,这样,空穴朝着根的方向向上行了一步。继续该过程直到 X 能被放入空穴中为止。这种策略也叫做上滤(percolate up)
类似的我们也可以声明一个最大堆,它使我们通过改变堆序性质能够有效的找出和删除最大元。因此,优先队列可以用来找出最大元和最小元,但这需要提前确定。

void insert(const Comparable& x)
{
    if(currentSize == array.size()-1)
        array.resize(array.size()*2);
    int hole = ++currentSize;
    for(;hole>1&&x<array[hole/2];hole/=2)
        array[hole] = array[hole/2];
    array[hole] = x;

如果要插入的元素是新的最小的元素从而一直上滤到根处,那么这种插入时间为 O(logN)。
2.deleteMin 操作:
deleteMin 的操作类似于 insert,首先找到最小元素是比较简单的,难的在于删除它,因为一旦删除堆顶的元素那么就会破坏堆序性质,因此我们需要重新调整。具体操作的方法是:当删除最小的元素,要在根结点处建立一个空穴。由于现在堆少了一个元素,因此堆中最后一个元素 X 必须移动到该堆的某个地方。如果 X 可以被放在空穴处则删除操作完成;如果不行,则将空穴的两个儿子中较小的移入空穴,这样就可以把空穴往下推一层。重复该步骤直到 X 可以被放入空穴中。因此我们的做法是将 X 置入沿着从根开始包含最小儿子的一条路径上的一个正确位置。这种策略叫做下滤(percolate down)

void deleteMin()
{
    if(isEmpty())
        throw UnderflowException();
    array[1] = array[currentSize--];
    percolateDown(1);
}
void deleteMin(Comparable& minItem)
{
    if(isEmpty())
        throw UnderflowException();
    minItem = array[1];
    array[1] = array[currentSize--];
    percolateDown(1);
}
void percolateDown(int hole)
{
    int child;
    Comparable tmp = array[hole];
    for(;hole*2<=currentSize; hole = child)
    {   child = hole * 2; 
        if(child!=currentSize&&array[child+1]<array[child])
            ++child;
        if(array[child]<tmp)
            array[hole] = array[child];
        else
            break;
    }
    array[hole] = tmp;      
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值