`
liyiwen007
  • 浏览: 108210 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

《算法导论》笔记--优先级队列

阅读更多

 

  优先级队列也是一种基础的数据结构,应用非常广泛,并且经常作为其它算法的一部分出现。优先级队列一般分最大优先级队列和最小优先级队列。这两种优先级队列只是为了适应不同场合的需要而进行区分实现,在算法上来讲没有什么本质的不同。因此下面只讲最大优先级队列,所记内容都同时对称地适用于最小优先级队列。

  最大优先级队列,是这样的一种队列结构,它的内部存放着一系列的元素,每个元素都对应着一个最优级,最大优先级队列不管各元素的入队顺序,在出队时,总是对应优先级最大的元素出队。比如对许多等待运行的进程来讲,进程调度器每次都取出一个优先级最高的进程执行一段时间,再取下一个优先级最高的进程,如此往复,就需要用到像最大优先级队列这样的结构。并且,最大优先级队列一般还会提供改变队列内元素优先级的操作。

最大优先级队列一般用二叉树来实现。因为考虑到,对于最大优先级队列来讲,我们关心的只是最大值,因此,这时的二叉树只需要具备下面这个性质,那么就可以实现了:

  性质A总是让二叉树中的每一个节点的key(也就是优先级)值比该节点的子节点的key值大

  保持性质A就可以在每次出队操作时,直接取根节点得到最大优先级的元素。然后再进行树结构的调整,使得取出根节点之后,二叉树仍然保持性质A。

  这样的二叉树可以保证,每个入队和出队的操作都在O(h)的时间内完成(h是树的高度)。入队和出队的操作,就不详细记述了(《算法导论》上讲得很清楚,网上也能找到一大堆的资料)。关键思想都是比较子树的父节点、左子节点、右子节点三个的值,然后将最大的调整到父节点,再对于与父节点进行交换的节点位置递归进行上述比较,最多的比较次数是沿根到叶的最大路径长(也就是树高h)。

  另外,考虑到这个树要保证的性质只有性质A,那么可以让这棵二叉树总是保持为完全二叉树(且不破坏性质A),这样树高就会是lgn,那么入队和出队操作的时间复杂度就是O(lgn)。这就比较理想了。

  对于一棵完全二叉树,我们可以用数组(而不是链表)方式来实现。因为对于数组实现的完全二叉树,index为i的节点,它的父节点的index是i/2,左子节点的index是i*2,右子节点的index是i*2+1。乘2和除2都是可以通过位移来实现的,效率上很好。而且通过保存元素个数,可以O(1)时间只找到处于树的最未的那个元素。用数组来实现还有一个好处,就是不需要在数据结构中再实现对父、子节点的指针存储,这样也省下了不少空间。这些特点都非常适合(也很好地改善了)优先级队列的实现。

 

 

以下是python代码实现:

class QueueElement:
    """
    Private class only for class QHeap. Suppling as a device to cobmine
    key and object together.
    """
    def __init__(self, obj, prio):
        self.key = prio
        self.obj = obj
    

class QHeap: # max heap
    """
    Private class
    Implement the basic data structure for Priority Queue.
    """
    def __init__(self, compare):
        self.HeapAry = [0]
        # method given by subclass. for config whether be a maxqueue or a minqueue.
        self.com = compare 
    def EnQueue(self, obj, priority):        
        self.HeapAry.append(QueueElement(obj, priority))
        i = self.QueueLen()
        while (i > 1) and self.com(self.HeapAry[i/2].key, self.HeapAry[i].key):
            self.HeapAry[i/2] ,self.HeapAry[i] = \
                self.HeapAry[i] ,self.HeapAry[i/2]
            i = i/2
        
    def __MakeHeapify(self, i):        
        if i > self.QueueLen()/2:
            return
        max_idx = i
        # find out the maximun(or minmun, judged by self.com method) one in 
        # parent,left and right node. Identify it be max_idx
        if self.com(self.HeapAry[max_idx].key, self.HeapAry[i*2].key):
            max_idx = i*2
        if i*2+1 <= self.QueueLen() and self.com(self.HeapAry[max_idx].key, self.HeapAry[i*2 + 1].key):
            max_idx = i*2 + 1
        # if the max_idx is not parent, exchange parent and max_idx element.
        if max_idx != i:
            self.HeapAry[max_idx] ,self.HeapAry[i] = \
                self.HeapAry[i] ,self.HeapAry[max_idx]
            self.__MakeHeapify(i*2)
    
    def DeQueue(self):
        head = self.HeapAry[1]
        last = self.HeapAry.pop()
        if (self.QueueLen() >= 1):
            self.HeapAry[1] = last
            self.__MakeHeapify(1)   
        return head.obj     
        
    def QueueLen(self):
        return len(self.HeapAry) - 1
    def Empty(self):
        return self.QueueLen() == 0
    
class MaxPrioQueue(QHeap):
    """
    Maximun priority queue.
    """
    def __init__(self):
        # max queue use x < y to judge the change node configration.
        self.com = lambda x, y: x < y
        self.HeapAry = []

class MinPrioQueue(QHeap):
    """
    Minmun priority queue.
    """
    def __init__(self):
        # max queue use x > y to judge the change node configration.
        self.com = lambda x, y: x > y
        self.HeapAry = []    

#-----------------------------------------------------------------
# for test only.

if __name__ == '__main__':
    h = MaxPrioQueue()
    chars = ['L', 'i', 'Y', 'i', 'W', 'e', 'n']
    keys  = [ 8 ,  4 ,  6 ,  3 ,  10,  9 ,  5 ]
    for i in range(0, len(chars)):
        h.EnQueue(chars[i], keys[i])
    result = []
    while not h.Empty():
        result.append(h.DeQueue())        
    print "length of result is %d:" % len(result)
    print "".join(result)
    
    h = MinPrioQueue()
    for i in range(0, len(chars)):
        h.EnQueue(chars[i], keys[i])
    result = []
    while not h.Empty():
        result.append(h.DeQueue())        
    print "length of result is %d:" % len(result)
    print "".join(result)

  

分享到:
评论

相关推荐

    算法导论15.2-1矩阵链最优括号化方案

    算法导论第三版练习题15.2-2的C++实现方案

    算法导论--编程经典

    算法导论--编程中经典的经典,值得每一位程序员用心品读

    算法导论习题解答 4-4

    《算法导论》是计算机科学领域的一本经典教材,它深入浅出地介绍了各种重要的算法,并提供了详尽的分析和实现。题目中的“4-4”可能指的是书中的第四章第四个习题,通常涉及图算法或者动态规划等主题。由于具体描述...

    在RT-Linux实现优先级继承机制.pdf

    优先级继承机制的实现可以分为两个步骤:第一步是分析RT-Linux的源代码,了解RT-Linux的调度算法和优先级机制;第二步是根据基本优先级继承协议对RT-Linux进行修改,添加优先级继承机制。 在RT-Linux中,优先级继承...

    算法导论课件-经典.rar

    《算法导论》是计算机科学领域的一本经典教材,它深入浅出地介绍了各种重要的算法和数据结构,为学习者提供了坚实的理论基础和实践技能。本压缩包“算法导论课件-经典.rar”显然是一个包含该课程相关资料的集合,...

    中科大算法导论答案1-13次全部 中科大算法导论答案1-13次全部

    中科大算法导论答案1-13次全部 中科大算法导论答案1-13次全部 中科大算法导论答案1-13次全部 中科大算法导论答案1-13次全部 中科大算法导论答案1-13次全部 中科大算法导论答案1-13次全部

    算法导论第15章课后习题答案

    算法导论第15章-动态规划的课后习题参考答案,对于算法爱好者而言,是不错的参考资料。

    算法导论第二十章习题解答

    《算法导论》第二十章习题解答涵盖了各种高级算法问题,主要涉及图论和网络流等内容。在这一章中,作者深入探讨了如何解决实际问题,如最短路径、最大流最小割以及网络调度等问题。以下是部分习题的解析和相关知识点...

    算法导论--英文版--附习题解析

    算法导论,英文版,附习题解析 Introduction to Algorithms, Second Edition Thomas H. Cormen Charles E. Leiserson Ronald L. Rivest Clifford Stein The MIT Press

    操作系统实验----动态优先级调度算法

    ### 操作系统实验——动态优先级调度算法 #### 背景与意义 在现代操作系统的设计与实现中,进程管理是核心部分之一。其中,进程调度算法的选择对系统的整体性能有着至关重要的影响。动态优先级调度算法是一种常用...

    算法导论--教师版

    本书详细讨论了数组、链表、栈、队列、哈希表、树(如二叉搜索树、红黑树)等基本数据结构,并探讨了它们在算法设计中的应用。 #### 排序算法 排序算法是算法领域中最常见的一类算法,用于将一组元素按照特定顺序...

    算法导论章节答案(31~35章)

    《算法导论》是计算机科学领域的一本经典教材,涵盖了广泛的算法分析和设计技术。这本书的第31至35章包含了许多关键的算法概念,这些章节深入探讨了不同的算法主题,对于理解和掌握算法有着至关重要的作用。以下是这...

    算法导论 1-7章学习笔记

    本次上传的文件包含《算法导论》课程前七章的学习笔记,内容涵盖了基础算法(如插入排序、归并排序)、递归方程的解法、数据结构(如堆、二叉搜索树)的操作与分析,以及图论算法(如BFS、DFS)等。该笔记详细记录了...

    操作系统实验--根据优先级模拟进程调度

    4. **调度算法**:实现调度逻辑,每次从队列中选取优先级最高的进程进行执行。 5. **时间片分配**:分配CPU时间片给选中的进程,模拟CPU上下文切换。 6. **进程状态转换**:模拟进程的就绪、运行、阻塞和结束状态。 ...

    算法导论原版-经典算法书籍,非常值得仔细推敲

    讲解算法导论的原版书籍,每个算法都提供伪码及正确性证明,值得一看

    算法导论--Thomas H. Cormen

    算法导论经典著作 Thomas H. Cormen--------算法“倚天屠龙”双剑

    PriorityQueue-MEX-Matlab 优先级队列 matlab

    MEX文件可以实现各种定制的数据结构和算法,以满足特定需求,比如在这个例子中,实现优先级队列。 在"PriorityQueue-MEX-Matlab"项目中,开发者可能创建了一个MEX接口,允许MATLAB程序调用C/C++实现的优先级队列。...

    算法导论第十五章习题解答

    《算法导论》是计算机科学领域的一本经典著作,它深入浅出地介绍了各种重要的算法,并提供了详尽的分析和实现。第十五章通常涉及图算法,包括最短路径、最小生成树、网络流等核心概念。在这个压缩包中,我们可能会...

    算法导论习题解答 4-1

    1. **最短路径问题**:Dijkstra算法是求解单源最短路径的常用方法,它通过维护一个优先队列来逐步确定从起点到各个节点的最短路径。Floyd-Warshall算法则能解决所有节点间的最短路径,通过动态规划的思想,逐次更新...

    算法导论4-7

    算法导论上的一个习题,第四章递归那章,4-7。 该源码提供一个对该题目算法的一个实现。

Global site tag (gtag.js) - Google Analytics