之前写过一个有序/无序列表来实现优先级队列的,在这里。
 这次,我们尝试一下用堆来实现。
堆
首先的话,这里默认的堆是小顶堆。
 堆,是二叉树的一种,更准确来说是完全二叉树,所以经常使用数组(python中用列表)来存储。如果对这一部分有问题,建议看这里。
堆的性质就是根部的结点最小(这里默认小顶堆),因为树的递归性质,对于每一个子树都成立。
堆支持插入和删除,一般删除都是指删除根节点,并且认为在操作之前堆是满足性质的。
插入
我们习惯的是先在列表的最后进行插入,然后此时一般会破坏堆的性质,我们就需要进行整理。整理的方法也很容易想到,破坏了也就是插入的叶子节点小于其根节点。
插入的一定是叶子,这个不用说了。
 不过看一下下面这种情况:
 
 在进行了一次的交换后,1成了4和5的根节点,但此时仍然不是一个堆,因为3>1,所以我们还需要沿着向根节点的路径一直走下去。
删除
因为删除是默认删除根节点,也就是pop出最小的元素,所以不能直接删除,我们将列表最后一个元素提到根节点,很明显这也是一个破坏了堆结构的行为,所以我们还需要整理。
 但这次,是顶上出了问题,所以我们要自顶向下。
从上往下选就有问题了,一般都是有两个孩子准备"上位"的,我们就需要选一个小一点的孩子。
 同样,只处理一处是不合适的,所以我们还是需要沿着较小孩子的路径向下走。
初始化
如果是一个从最开始就这样插入删除的,那一定是堆。但就怕半路上要整一个堆,就比较烦。
首先,我们来达成几个共识:
- 对于一个无序序列要整理成堆,我们应当采用的是自顶向下的整理方式
- 如果是使用自顶向下的排序方式,我们只需要处理非叶子结点
- 如果是自顶向下,我们需要从最后一个非叶子结点开始
首先,自顶向下的方式,本身就是通过给定一个子树的根节点,一直往下直到叶子结点,所以是不要处理叶子结点的;
 另外,自顶向下本身也就是一条路径,如果是破坏能实现构成堆,但如果是无序的,如果从根节点开始,我们可以看一下这个:
 
 第一次,将7-3对换,然后走到3位置上(现在为7),然后2-7对换,此时根节点已经结束了,2就没有机会到根节点了。
但是,如果我们采用的是从最后一个非叶子结点,首先是一定能将这个子树整理成堆的(撑死就两个孩子,一定可以的),然后上面一层都的左右孩子都是堆,调用自顶向下就能实现整理了。
 细心的可以发现,其实我们在删除的时候,左右子树就都是堆,所以成立。
然后,我们讨论一下自底向上的方式。
 我们当时是在最后插入一个结点的情况下,使用了该方法,所以如果处理需要从第一个结点开始,并且因为从底下开始的性质,是一定要到最后一个结点。
那么也就相当于是从空堆开始,每次插入一个……,那tm当然能成堆了。
 不过,要知道叶子节点数=非叶子结点数(+1),所以这个方法直接把难度拉大了一倍。
实现
有了上面的描述,这部分应该是不难的。
用到了之前的一个基类,也贴出来了。
class PriorityQueueBase():
    """Abstract base class for a priority queue"""
    class _Item():
        """lightweight composite to store priority queue items"""
        __slots__ = '_key', '_value'
        def __init__(self,k,v):
            self._key = k
            self._value = v
        def __lt__(self,other):
            # 这样就可以直接比较两个结点,而不需要比较key
            return self._key < other._key
     Python实现优先级队列:堆的数据结构解析与操作
Python实现优先级队列:堆的数据结构解析与操作
        
 
                   
                   
                   
                   本文介绍了如何使用堆来实现优先级队列。堆是一种特殊的完全二叉树,遵循小顶堆性质,即根节点是最小元素。文中详细探讨了堆的插入、删除和初始化操作,以及维护堆性质的方法。插入操作需要自底向上调整,删除则自顶向下。初始化无序序列为堆时,采用自顶向下的策略,从最后一个非叶子节点开始处理。堆的插入和删除时间复杂度为O(logn),相比其他方法更高效。
本文介绍了如何使用堆来实现优先级队列。堆是一种特殊的完全二叉树,遵循小顶堆性质,即根节点是最小元素。文中详细探讨了堆的插入、删除和初始化操作,以及维护堆性质的方法。插入操作需要自底向上调整,删除则自顶向下。初始化无序序列为堆时,采用自顶向下的策略,从最后一个非叶子节点开始处理。堆的插入和删除时间复杂度为O(logn),相比其他方法更高效。
           最低0.47元/天 解锁文章
最低0.47元/天 解锁文章
                           
                       
       
           
                 
                 
                 
                 
                 
                
               
                 
                 
                 
                 
                
               
                 
                 扫一扫
扫一扫
                     
              
             
                   416
					416
					
 被折叠的  条评论
		 为什么被折叠?
被折叠的  条评论
		 为什么被折叠?
		 
		  到【灌水乐园】发言
到【灌水乐园】发言                                
		 
		 
    
   
    
   
             
            


 
            