1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
| ''' 优先队列: 取出元素的顺序是依照优先级(关键字)大小,而不是元素加入队列的先后顺序。
若数组或链表实现优先队列
数组 插入 --- 元素总是插入尾部,O(1) 删除 --- 查找最大(小)关键字 O(n) 从数组中删除,需要移动元素 O(n) 链表 插入 --- 元素总是插入链表的头部 O(1) 删除 --- 查找最大(小)关键字 O(n) 删去结点 O(1) 有序数组 插入 --- 找到适合的位置 O(n)或O(log n) 移动元素并插入 O(n) 删除 --- 删去最后一个元素 O(1) 有序链表 插入 --- 找到适合的位置 O(n) 插入元素 O(1) 删除 --- 删除首元素或者最后的元素 O(1)
''' ''' 若使用二叉搜索树 在平衡条件下,删除都是 O(log2 n) 但是多删除几个以后,树就歪了,不平衡了,效率开始下降向 O(N)变化。
'''
class HeapStruct(): def __init__(self,elements=[None],addre=0,capacity=0): self.elements = elements self.addre = addre self.capacity = capacity def MaxHeapCreate(self,MaxSize): print(' 若插入数值,请确保插入数值在 100 以内 。结点容量为%d'%MaxSize) self.elements = [None] * (MaxSize+1) self.capacity = MaxSize self.elements[0] = self.MaxData() print('self capacity = %s'%self.capacity) def MaxData(self): return 100
def Insert(self,item): if self.IsFull(): print('最大堆已满') return i = self.addre + 1 if self.elements[0] <= item: print('插入数值大小超限') return while self.elements[i//2] < item: print(self.elements[i//2],item) self.elements[i] = self.elements[i//2] i //= 2 self.elements[i] = item self.addre += 1 def IsFull(self): if self.addre == self.capacity: print( self.addre,self.capacity) return 1 return 0 def IsEmpty(self): if self.addre == 0: return 1 return 0
def DeleteMax(self): if self.IsEmpty(): print('最大堆已空。') return maxitem = self.elements[1] temp = self.elements[self.addre] self.elements[self.addre] = None self.addre -= 1 parent = 1 while parent*2 <= self.addre: left_child = parent * 2 if self.addre != left_child and self.elements[left_child+1] > self.elements[left_child]: child = left_child + 1 else: child = left_child if self.elements[child] >= temp: self.elements[parent] = self.elements[child] parent = child elif self.elements[child] < temp: self.elements[parent] = temp return maxitem self.elements[parent] = temp return maxitem
h = HeapStruct() h.MaxHeapCreate(50)
h.Insert(22) h.Insert(12) h.Insert(13) h.Insert(44) h.Insert(44) h.Insert(44) h.Insert(50) print(h.elements,'\n',h.addre) h.DeleteMax() print(h.elements,'\n',h.addre)
''' 最大堆的建立: 方法一: 像上面不断插入来建立最大堆。 时间复杂度 O(Nlog N) 因为一次擦乳的时间复杂度是二分法类似的 log N ,循环n次。 方法二: 在线性时间复杂度下,建立最大堆。 找到最后一个节点的父节点,从它开始进行节点shiftdown下沉操作,直到结束。该方法不难。 多次shiftdown 会完成一个堆化 heapify 形成一个堆,但是只有从倒数第一个非叶结点,逐次往上shiftdown才会形成堆,不是随便一个shiftdown都能形成堆的。 O(N) 步骤一:将n个元素按输入顺序存入,先满足完全二叉树的结构特性。 步骤二:调整结点位置,满足最大堆的有序特性。 先从倒数第一个有儿子的结点调起,把它和最大的儿子比大小, 类似于删除中的部分操作,将它和儿子调整成堆。 再从倒数第二个有儿子的... 重复步骤二 ... 直到根结点。 T = O(n) 推导过程不难,可以看 https://blog.csdn.net/SheIsSDEatNYC/article/details/109153708 等比等差数列,错位相减一下就好了。 '''
def BuildHeap_new_mathed(A,N): def shiftdown(A,i,N): parent = i temp = A[i] while parent * 2 <= N: left_child = parent * 2 if N != left_child and A[left_child + 1] > A[left_child]: child = left_child + 1 else: child = left_child if A[child] >= temp: A[parent] = A[child] parent = child elif A[child] < temp: A[parent] = temp return A[parent] = temp for j in range(int(N/2),0,-1): shiftdown(A,j,N)
A =[0,1,5,6,2,4,3,8,9,7,10,13,12,11] BuildHeap_new_mathed(A,len(A)-1) print('用heapify堆化,O(N),shiftdown不断下沉的方法构建堆为:\n',A,'\n')
class HeapStruct_2(): def __init__(self,elements=[None],addre=0,capacity=0): self.elements = elements self.addre = addre self.capacity = capacity def MinHeapCreate(self,Capacity_Size): print(' 若插入数值,请确保插入数值在 0 以上 。结点容量为%d'%Capacity_Size) self.elements = [None] * (Capacity_Size+1) self.capacity = Capacity_Size self.elements[0] = self.MinData() print('self capacity = %s'%self.capacity) def MinData(self): return 0 def Insert(self,item): if self.IsFull(): print('最小堆已满') return i = self.addre + 1 if self.elements[0] >= item: print('插入数值大小小于下限') return while self.elements[i//2] > item: print(self.elements[i//2],item) self.elements[i] = self.elements[i//2] i //= 2 self.elements[i] = item self.addre += 1 def IsFull(self): if self.addre == self.capacity: print( self.addre,self.capacity) return 1 return 0 def IsEmpty(self): if self.addre == 0: return 1 return def DeleteMin(self): if self.IsEmpty(): print('最小堆已空。') return minitem = self.elements[1] temp = self.elements[self.addre] self.elements[self.addre] = None self.addre -= 1 parent = 1 while parent*2 <= self.addre: left_child = parent * 2 if self.addre != left_child and self.elements[left_child+1] < self.elements[left_child]: child = left_child + 1 else: child = left_child if self.elements[child] <= temp: self.elements[parent] = self.elements[child] parent = child elif self.elements[child] > temp: self.elements[parent] = temp return minitem self.elements[parent] = temp return minitem
h = HeapStruct_2() h.MinHeapCreate(12)
h.Insert(22) h.Insert(12) h.Insert(13) h.Insert(44) h.Insert(44) h.Insert(44) h.Insert(50) print(h.elements,'\n',h.addre) h.DeleteMin() print(h.elements,'\n',h.addre)
|