zoukankan      html  css  js  c++  java
  • 二叉堆

    二叉堆

    1 基于二叉堆的优先队列

    在优先级队列中,队列中的项的逻辑顺序由它们的优先级确定。最高优先级项在队列的前面,最低优先级的项在后面。因此,当你将项排入优先级队列时,新项可能会一直移动到前面。

    我们只使用一个单一的列表作为二叉堆的内部表示。

    二叉堆有两个常见的变体:最小堆(其中最小的键总是在前面)和最大堆(其中最大的键值总是在前面)。

    我们将实现最小堆。

    2 二叉堆实现

    利用二叉树的对数性质来表示我们的堆。

    2.1 完整二叉树

    一个完整的二叉树是一个树,其中每个层都有其所有的节点,除了树的最底层,从左到右填充。

    2.2 堆的属性

    可以使用单个列表来表示它。

    父节点的左子节点(在位置 p 处) 是在列表中位置 2p 中找到的节点。 类似地,父节点的右子节点在列表中的位置 2p + 1。为了找到树中任意节点的父节点,我们可以简单地使用 Python 的整数除法。

    1539144165586

    堆的排序属性如下:在堆中,对于具有父 p 的每个节点 x,p 中的键小于或等于 x 中的键。

    2.3 堆操作

    2.3.1 init 函数

    一个空的二叉堆有一个单一的零作为 heapList 的第一个元素,这个零只是放那里,用于以后简单的整数除法。

    def __init__(self):
    	self.heapList = [0]
    	self.currentSize = 0
    

    2.3.2 insert 函数

    将项添加到列表中最简单,最有效的方法是将项附加到列表的末尾。 它维护完整的树属性。但可能违反堆结构属性。可以编写一个方法,通过比较新添加的项与其父项,我们可以重新获得堆结构属性。 如果新添加的项小于其父项,则我们可以将项与其父项交换。

    下图展示了将新添加的项替换到其在树中的适当位置所需的操作。

    1539144683528

    当添加完一个新项后,需要对二叉堆进行维护,由 perUp 函数接管,它在树中向上遍历一个新项并正确定位该新项。

    def perUp(self, i):
    	while i // 2 > 0:
    		if self.heapList[i] < self.heapList[i // 2]:
    			tmp = self.heapList[i // 2]
    			self.heapList[i // 2] = self.heapList[i]
    			self.heapList[i] = tmp
    		i = i // 2
    
    def insert(self, k):
    	self.heapList.append(k)
    	self.currentSize += 1
    	self.perUp(self.currentSize)
    

    2.3.3 delMin 函数

    堆属性要求树的根是树中的最小项,所以找到最小项很容易。

    难点在根被删除后恢复堆结构和堆顺序属性。

    1. 通过获取列表中的最后一个项并将其移动到根位置来恢复根项。
    2. 通过将新的根节点沿着树向下推到其正确位置来恢复堆顺序属性。

    1539247149051

    为了维护堆顺序属性,我们所需要做的是将根节点和最小的子节点交换。

    将节点和其子节点重复交换,直到节点被交换到正确的位置,使它小于两个子节点。

    percDown 和 minChild 方法实现树交换节点。percDown 方法确保最大的子节点总是沿着树向下移动。

    def minChild(self, i):
    	if i * 2 + 1 > self.currentSize:
    		return i * 2
    	else:
    		if self.heapList[i*2] < self.heapList[i*2+1]:
    			return i * 2
    		else:
    			return i * 2 + 1
    
    def perDown(self, i):
    	while (i * 2) <= self.currentSize:
    		mc = self.minChild(i)
    		if self.heapList[i] > self.heapList[mc]:
    			tmp = self.heapList[i]
    			self.heapList[i] = self.heapList[mc]
    			self.heapList[mc] = tmp
    		i = mc
    

    delMin 函数的代码。

    def delMin(self):
    	retval = self.heapList[1]
    	self.heapList[1] = self.heapList[self.currentSize]
    	self.currentSize = self.currentSize - 1
    	self.heapList.pop()
    	self.perDown(1)
    	return retval
    

    2.3.4 buildHeap 函数

    buildHeap 函数用于构建整个堆。

    1539247490777

    def buildHeap(self, alist):
    	i = len(alist) // 2
    	self.currentSize = len(alist)
    	self.heapList = [0] + alist[:]
    	while i > 0:
    		self.perDown(i)
    		i = i - 1
    

    2.4 完整代码

    class BinHeap(object):
        def __init__(self):
            self.heapList = [0]
            self.currentSize = 0
    
        def perUp(self, i):
            while i // 2 > 0:
                if self.heapList[i] < self.heapList[i // 2]:
                    tmp = self.heapList[i // 2]
                    self.heapList[i // 2] = self.heapList[i]
                    self.heapList[i] = tmp
                i = i // 2
    
        def insert(self, k):
            self.heapList.append(k)
            self.currentSize += 1
            self.perUp(self.currentSize)
    
        def minChild(self, i):
            if i * 2 + 1 > self.currentSize:
                return i * 2
            else:
                if self.heapList[i*2] < self.heapList[i*2+1]:
                    return i * 2
                else:
                    return i * 2 + 1
    
        def perDown(self, i):
            while (i * 2) <= self.currentSize:
                mc = self.minChild(i)
                if self.heapList[i] > self.heapList[mc]:
                    tmp = self.heapList[i]
                    self.heapList[i] = self.heapList[mc]
                    self.heapList[mc] = tmp
                i = mc
    
        def delMin(self):
            retval = self.heapList[1]
            self.heapList[1] = self.heapList[self.currentSize]
            self.currentSize = self.currentSize - 1
            self.heapList.pop()
            self.perDown(1)
            return retval
    
        def buildHeap(self, alist):
            i = len(alist) // 2
            self.currentSize = len(alist)
            self.heapList = [0] + alist[:]
            while i > 0:
                self.perDown(i)
                i = i - 1
    
    
    if __name__ == '__main__':
        bh = BinHeap()
        bh.buildHeap([9, 5, 6, 2, 3])
        print(bh.delMin())
        print(bh.delMin())
        print(bh.delMin())
        print(bh.delMin())
        print(bh.delMin())
    

  • 相关阅读:
    PAT (Advanced Level) 1114. Family Property (25)
    PAT (Advanced Level) 1113. Integer Set Partition (25)
    PAT (Advanced Level) 1112. Stucked Keyboard (20)
    PAT (Advanced Level) 1111. Online Map (30)
    PAT (Advanced Level) 1110. Complete Binary Tree (25)
    PAT (Advanced Level) 1109. Group Photo (25)
    PAT (Advanced Level) 1108. Finding Average (20)
    PAT (Advanced Level) 1107. Social Clusters (30)
    PAT (Advanced Level) 1106. Lowest Price in Supply Chain (25)
    PAT (Advanced Level) 1105. Spiral Matrix (25)
  • 原文地址:https://www.cnblogs.com/banshaohuan/p/9773430.html
Copyright © 2011-2022 走看看