C++实现及理论https://www.cnblogs.com/polly333/category/720001.html
https://github.com/liuyubobobo/Play-with-Algorithms
python实现https://github.com/ShiveryMoon/Imooc-Algorithm-PythonEdition
优先队列
二叉堆(若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。)
最大堆:对于从1开始索引
从0开始索引
class MaxHeap(object): def __init__(self,max=100000): self.heapList=[0] self.currentSize=0 self.maximum=max def shiftUp(self,i):#2.然后向上移动变成最大堆 currentvalue=self.heapList[i] while i//2>0:#i的父节点>0 if self.heapList[i//2] < currentvalue: self.heapList[i]=self.heapList[i//2] #优化:赋值替代交换 i=i//2 else: break self.heapList[i]=currentvalue def insert(self,k):#1.插入,入堆(向堆中插入新元素到末尾), self.heapList.append(k) self.currentSize+=1 self.shiftUp(self.currentSize) if self.currentSize>self.maximum: #在最大堆中这个操作会保留m个最小的元素。 self.delFirst() def shiftDown(self,i):#2然后向下移动变成最大堆 currentvalue=self.heapList[i] while i*2<=self.currentSize:#当i有子节点(左子节点) mc=self.maxChild(i)#i是否有右子节点,有则比较i的子节点大小 if currentvalue < self.heapList[mc]:#当前值<较大的那个子节点,交换,然后继续循环 self.heapList[i]=self.heapList[mc] i=mc else: break self.heapList[i]=currentvalue def maxChild(self,i): if i*2+1>self.currentSize:#i没有右子节点 return i*2 else:#i有右子节点,比较两子节点大小 if self.heapList[i*2]>self.heapList[i*2+1]:#左子节点>右子节点 return i*2 else: return i*2+1 # 之所以叫delFirst是因为这个函数可以兼容最大堆和最小堆 def delFirst(self): #1出堆(根节点出堆,最末子节点补到根节点位置), retval=self.heapList[1] if self.currentSize==1:#二叉堆只有一个节点时 self.currentSize-=1 self.heapList.pop() return retval self.heapList[1]=self.heapList[self.currentSize]#二叉堆末尾的节点覆盖到根节点 self.heapList.pop()#删除末尾元素 self.currentSize-=1 self.shiftDown(1)#下移 return retval def buildHeap(self,alist): #heapify O(n)级别 self.heapList=[0]+alist[:]#首元素为0,将列表从顺序1加入到堆中 self.currentSize=len(alist) i=self.currentSize//2 while i>0: self.shiftDown(i) i-=1 overflow=self.currentSize-self.maximum for i in range(overflow): self.delFirst() def HeapSort(self,alist): self.buildHeap(alist) sortedList=[self.delFirst() for x in range(self.currentSize)]#循环返回最大堆的根节点(根节点值是最大的)直到堆里没有元素 sortedList.reverse()#从小到大排序 return sortedList def HeapSortInPlace(self,alist):#原地堆排序,将末尾元素与根节点交换然后shiftDown,然后重复 self.buildHeap(alist) while self.currentSize>1: self.heapList[1],self.heapList[self.currentSize]=self.heapList[self.currentSize],self.heapList[1] self.currentSize-=1 self.shiftDown(1) return self.heapList[1:]
最小堆:#在N个元素中选出前M个元素
class MinHeap(MaxHeap): #最小堆,继承自MaxHeap,覆盖了父类的上浮和下沉操作,酌情使用。 def __init__(self): super(MaxHeap, self).__init__() def shiftUp(self,i): currentvalue=self.heapList[i] while i//2 > 0: if self.heapList[i//2] > currentvalue: self.heapList[i]=self.heapList[i//2] i//2 else: break self.heapList[i] = currentvalue def shiftDown(self,i): currentvalue=self.heapList[i] while i*2<=self.currentSize: mc=self.minChild(i) if currentvalue > self.heapList[mc]: self.heapList[i]=self.heapList[mc] i=mc else: break self.heapList[i]=currentvalue 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
索引堆:比较data,交换index
表格中第一行代表i、第二行indexList[i],第三行items[indexList[i]]
#直接使用python的dict对象可以非常容易地实现索引堆。 # 在buildHeap中 将key关键字列表化,这样i对应的列表的索引,index对应的列表值,data就是字典的value # 比较的是data,交换的是列表的值即index,字典中的值没有发生改变,然后通过index在字典中查找 class IndexMaxHeap(object): def __init__(self): self.indexList=[0] self.items={} self.currentSize=0 def shiftUp(self,i): currentvalue=self.items[self.indexList[i]]#当前值 currentindex=self.indexList[i]#当前值对应的用户索引 while i//2>0: if self.items[self.indexList[i//2]] < currentvalue: self.indexList[i]=self.indexList[i//2]#交换字典索引 i=i//2 else: break self.indexList[i]=currentindex def insert(self,k,value): self.indexList.append(k) self.items[k]=value self.currentSize+=1 self.shiftUp(self.currentSize) def shiftDown(self,i): currentvalue=self.items[self.indexList[i]] currentindex=self.indexList[i] while i*2<=self.currentSize:#当i有子节点(左子节点) mc=self.maxChild(i)#i是否有右子节点,有则比较i的子节点大小 if currentvalue < self.items[self.indexList[mc]]:#当前值<较大的那个子节点,交换,然后继续循环 self.indexList[i]=self.indexList[mc] i=mc else: break self.indexList[i]=currentindex def maxChild(self,i): if i*2+1>self.currentSize: return i*2 else: if self.items[self.indexList[i*2]]>self.items[self.indexList[i*2+1]]: return i*2 else: return i*2+1 def delFirst(self): retval=self.items[self.indexList[1]] del self.items[self.indexList[1]]#删除字典元素 if self.currentSize==1: self.currentSize-=1 self.indexList.pop() return retval self.indexList[1]=self.indexList[self.currentSize]#将末尾元素的索引赋值到根节点 self.indexList.pop()#删除末尾元素的索引 self.currentSize-=1 self.shiftDown(1)#进行下移 return retval def buildHeap(self,items): self.items=items self.indexList=[0]+list(self.items.keys()) self.currentSize=items.__len__() i=self.currentSize//2 while i>0: self.shiftDown(i) i-=1 def getItem(self,i):#这里的i就是key return self.items[i] def maxItemIndex(self): return self.indexList[1] def change(self,k,newValue): if k not in self.indexList: raise Exception('%s is not exist!' % k) self.items[k]=newValue #index() 函数用于从列表中找出某个值第一个匹配项的索引位置。 i=self.indexList.index(k) #index方法的复杂度是O1,根本不需要实现reverse列表。我猜python内部就是靠reverse列表来实现这个index方法的。 self.shiftDown(i)#如果变小下移 self.shiftUp(i)#如果变大上移 return True测试用例:
heap=IndexMaxHeap() items={'John':21,'Lucy':14,'Jesscia':17,'张三':32,'李四':11} #按照分数构成最大堆 heap.buildHeap(items) heap.insert('Dark',15) print('最高分: %s %s' % (heap.maxItemIndex(),heap.items[heap.maxItemIndex()])) print('Lucy多少分? %s' % heap.getItem('Lucy')) #将Lucy的分数提高到50 heap.change('Lucy',50) print('最高分: %s %s' % (heap.maxItemIndex(),heap.items[heap.maxItemIndex()])) heap.delFirst() print('最高分: %s %s' % (heap.maxItemIndex(),heap.items[heap.maxItemIndex()]))