【数据结构学习笔记】优先级队列

概念

优先级队列是0个或多个元素的集合,每个元素都有一个优先权值。在最小优先级队列中,查找和删除的元素都是优先级最小的元素;在最大优先级队列中,查找和删除的元素都是优先级最大的元素。优先级队列元素可以有相同的优先级,这时候查找与删除可以按任意顺序处理。

抽象类:

template<class T>
class maxPriorityQueue
{
    public:
        virtual ~maxPriorityQueue() {}
        virtual bool empty() const=0;//返回true,当且仅当队列为空
        virtual int size() const=0;//返回队列的元素个数
        virtual const T& top()=0;//返回优先级最大的元素的引用
        virtual void pop()=0;//删除队首元素
        virtual void push(const T& theElement)=0;//插入元素theElement
};

定义

一棵大根树(小根树)是这样的一棵树:其中每个结点的值都大于(小于)或等于其子节点(如果有)的值。

一个大根堆(小根堆)既是大根数(小根树)也是完全二叉树。

大根堆的插入

把新元素插入最后一个位置的新节点,然后沿着从新节点到根节点的路径,执行一趟起泡操作,将新元素与其父节点的元素比较交换,知道后者大于或等于前者为止。

template<class T>
void maxHeap<T>::push(const T& theElement)
{
    //将theElement插入大根堆
    //必要时增加数组长度
    if(heapSize==arrayLength-1)
    {
        //数组长度加倍
        changeLength1D(heap,arrayLength,2*arrayLength);
        arrayLength*=2;
    }
    
    //寻找插入位置
    //currentNode从新叶子向上移动
    int currentNode=++heapSize;
    while(currentNode!=1 && heap[currentNode/2]<theElement)
    {
        //不能插到heap[currentNode]
        heap[currentNode]=heap[currentNode/2];//把元素向下移动
        currentNode/=2;//currentNode移向双亲
    }
    heap[currentNode]=theElement;
}

大根堆的删除

在大根堆删除一个元素,就是删除根节点的元素。删除根节点后,将最后一个元素删除,并且变成新的根节点(使其还是完全二叉树)。此时二叉树需要重新排序。把此时的根节点和左右孩子元素大者进行交换,不停交换直到形成大根堆。时间复杂度为O(height)=O(logn)。

template<class T>
void maxHeap<T>::pop()
{
    //删除最大元素
    //如果堆为空,抛出异常
    if(heapSize==0)
        throw queueEmpty();
    //删除最大元素
    heap[1].~T();
    //删除最后一个元素,重新建立堆
    T lastElement=heap[heapSize--];
    //从根开始,为最后一个元素寻找位置
    int currentNode=1;
    int child=2;
    while(child<=heapSize)
    {
        //heap[child]应该是currentNode更大的孩子
        if(child<heapSize && heap[child]<heap[child+1])
            child++;
        //可以放在heap[currentNode]吗
        if(lastElement>=heap[child]
            break;//可以
        //不可以
        heap[currentNode]=heap[child];//把孩子child向上移动
        currentNode=child;//向下移动一层寻找位置
        child*=2;
    }
    heap[currentNode]=lastElement;
}

大根堆的初始化

为了构建初始的非空堆,需要在空堆中执行n次插入操作。插入操作需要总时间为O(nlogn)。从最后一棵子树开始检查是否是大根堆,如果不是则调整,是则检查倒数第二棵,一直检查到根节点的树。

template<class T>
void maxHeap::initialize(T *theHeap,int theSize)
{
    //在数组theHeap[1:theSize]中建大根堆
    delete[] heap;
    heap=theHeap;
    heapSize=theSize;

    //堆化,从最后一棵子树开始判断是否是最大堆,然后到倒数第二....
    for(int root=heapSize/2;root>=1;root--)
    {
        T rootElement=heap[root];
        //寻找位置
        int child=2*root;
        while(child<=heapSize)
        {
            //heap[child]应该是兄弟中较大者
            if(child<heapSize && heap[child]<heap[child+1])
                child++;
            //可以把元素rootElement放在heap[currentNode]吗
            if(rootElement>=heap[child])
                break;//可以
            //不可以
            heap[child/2]=heap[child];//把最大孩子和根植交换
            child*=2;
        }
        heap[child/2]=rootElement;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值