पाइथन में मिन-हीप्स के लिए हीपेक मॉड्यूल शामिल है, लेकिन मुझे अधिकतम हीप की आवश्यकता है। पायथन में अधिकतम-ढेर कार्यान्वयन के लिए मुझे क्या उपयोग करना चाहिए?
पाइथन में मिन-हीप्स के लिए हीपेक मॉड्यूल शामिल है, लेकिन मुझे अधिकतम हीप की आवश्यकता है। पायथन में अधिकतम-ढेर कार्यान्वयन के लिए मुझे क्या उपयोग करना चाहिए?
जवाबों:
सबसे आसान तरीका कुंजी के मूल्य को उल्टा करना और heapq का उपयोग करना है। उदाहरण के लिए, 1000.0 को -1000.0 और 5.0 को -5.0 में बदल दें।
heapq
है कि कोई उल्टा प्रदान नहीं करता है।
heapq
, और इससे अच्छा कोई विकल्प नहीं है।
int
/ के लिए मैप नहीं करता है float
, तो आप उन्हें एक उल्टे __lt__
ऑपरेटर के साथ कक्षा में लपेटकर ऑर्डर को उल्टा कर सकते हैं ।
आप उपयोग कर सकते हैं
import heapq
listForTree = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
heapq.heapify(listForTree) # for a min heap
heapq._heapify_max(listForTree) # for a maxheap!!
यदि आप तत्वों को पॉप करना चाहते हैं, तो उपयोग करें:
heapq.heappop(minheap) # pop from minheap
heapq._heappop_max(maxheap) # pop from maxheap
_heapify_max
, _heappushpop_max
, _siftdown_max
, और _siftup_max
।
जब आप उन्हें ढेर में संग्रहीत करते हैं, या अपनी ऑब्जेक्ट तुलना को उल्टा करते हैं, तो इसका समाधान यह है:
import heapq
class MaxHeapObj(object):
def __init__(self, val): self.val = val
def __lt__(self, other): return self.val > other.val
def __eq__(self, other): return self.val == other.val
def __str__(self): return str(self.val)
अधिकतम-ढेर का उदाहरण:
maxh = []
heapq.heappush(maxh, MaxHeapObj(x))
x = maxh[0].val # fetch max value
x = heapq.heappop(maxh).val # pop max value
लेकिन आपको अपने मूल्यों को लपेटने और उतारने के लिए याद रखना होगा, जिसके लिए यह जानना आवश्यक है कि क्या आप एक मिनट या अधिकतम-ढेर के साथ काम कर रहे हैं।
MinHeap
और MaxHeap
ऑब्जेक्ट्स के लिए कक्षाएं जोड़ना आपके कोड को सरल बना सकता है:
class MinHeap(object):
def __init__(self): self.h = []
def heappush(self, x): heapq.heappush(self.h, x)
def heappop(self): return heapq.heappop(self.h)
def __getitem__(self, i): return self.h[i]
def __len__(self): return len(self.h)
class MaxHeap(MinHeap):
def heappush(self, x): heapq.heappush(self.h, MaxHeapObj(x))
def heappop(self): return heapq.heappop(self.h).val
def __getitem__(self, i): return self.h[i].val
उदाहरण का उपयोग:
minh = MinHeap()
maxh = MaxHeap()
# add some values
minh.heappush(12)
maxh.heappush(12)
minh.heappush(4)
maxh.heappush(4)
# fetch "top" values
print(minh[0], maxh[0]) # "4 12"
# fetch and remove "top" values
print(minh.heappop(), maxh.heappop()) # "4 12"
list
__init__ के लिए एक वैकल्पिक पैरामीटर जोड़ा है जिस स्थिति में मैं कॉल करता हूं heapq.heapify
और एक heapreplace
विधि भी जोड़ता हूं ।
मानों को 1 से गुणा करें
तुम वहाँ जाओ। सभी उच्चतम संख्याएं अब सबसे कम और इसके विपरीत हैं।
बस याद रखें कि जब आप मूल मूल्य को फिर से प्राप्त करने के लिए एक तत्व को -1 से गुणा करते हैं।
मैंने हाइक के अधिकतम हीप संस्करण को लागू किया और इसे PyPI को प्रस्तुत किया। (हीपेक मॉड्यूल सीपीथॉन कोड का बहुत मामूली परिवर्तन।)
https://pypi.python.org/pypi/heapq_max/
https://github.com/he-zhe/heapq_max
स्थापना
pip install heapq_max
प्रयोग
tl; dr: सभी कार्यों के लिए '_max' को छोड़कर हीप मॉड्यूल के समान।
heap_max = [] # creates an empty heap
heappush_max(heap_max, item) # pushes a new item on the heap
item = heappop_max(heap_max) # pops the largest item from the heap
item = heap_max[0] # largest item on the heap without popping it
heapify_max(x) # transforms list into a heap, in-place, in linear time
item = heapreplace_max(heap_max, item) # pops and returns largest item, and
# adds new item; the heap size is unchanged
यदि आप ऐसी कुंजियाँ सम्मिलित कर रहे हैं जो तुलनीय हैं, लेकिन इंट-लाइक नहीं हैं, तो आप संभावित रूप से उन पर तुलनात्मक ऑपरेटरों को ओवरराइड कर सकते हैं (यानी <= बन> और> <=) बन जाते हैं। अन्यथा, आप heapq मॉड्यूल में heapq._siftup को ओवरराइड कर सकते हैं (यह अंत में केवल पायथन कोड है)।
# If available, use C implementation
) के बाद कुछ कोड है जो टिप्पणी का वर्णन करता है।
import heapq
heap = [23, 7, -4, 18, 23, 42, 37, 2, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
heapq.heapify(heap)
print(heapq.nlargest(3, heap)) # [42, 42, 37]
print(heapq.nsmallest(3, heap)) # [-4, -4, 2]
इंट क्लास का विस्तार करना और __lt__ को ओवरराइड करना एक तरीका है।
import queue
class MyInt(int):
def __lt__(self, other):
return self > other
def main():
q = queue.PriorityQueue()
q.put(MyInt(10))
q.put(MyInt(5))
q.put(MyInt(1))
while not q.empty():
print (q.get())
if __name__ == "__main__":
main()
मैंने एक ढेर रैपर बनाया है जो एक अधिकतम-ढेर बनाने के लिए मूल्यों को प्रभावित करता है, साथ ही पुस्तकालय को अधिक ओओपी-जैसे बनाने के लिए एक न्यूनतम-ढेर के लिए एक आवरण वर्ग। यहाँ है जिस्ट। तीन वर्ग हैं; हीप (अमूर्त वर्ग), हीपमिन, और हीपमैक्स।
तरीके:
isempty() -> bool; obvious
getroot() -> int; returns min/max
push() -> None; equivalent to heapq.heappush
pop() -> int; equivalent to heapq.heappop
view_min()/view_max() -> int; alias for getroot()
pushpop() -> int; equivalent to heapq.pushpop
यदि आप अधिकतम ढेर का उपयोग करके सबसे बड़ा K तत्व प्राप्त करना चाहते हैं, तो आप निम्नलिखित चाल कर सकते हैं:
nums= [3,2,1,5,6,4]
k = 2 #k being the kth largest element you want to get
heapq.heapify(nums)
temp = heapq.nlargest(k, nums)
return temp[-1]
nlargest
यहाँ देखें -> github.com/python/cpython/blob/…
इसहाक टर्नर के उत्कृष्ट जवाब के बाद , मैं अधिकतम ढेर का उपयोग करते हुए मूल के के क्लॉस्ट पॉइंट्स के आधार पर एक उदाहरण रखूंगा।
from math import sqrt
import heapq
class MaxHeapObj(object):
def __init__(self, val):
self.val = val.distance
self.coordinates = val.coordinates
def __lt__(self, other):
return self.val > other.val
def __eq__(self, other):
return self.val == other.val
def __str__(self):
return str(self.val)
class MinHeap(object):
def __init__(self):
self.h = []
def heappush(self, x):
heapq.heappush(self.h, x)
def heappop(self):
return heapq.heappop(self.h)
def __getitem__(self, i):
return self.h[i]
def __len__(self):
return len(self.h)
class MaxHeap(MinHeap):
def heappush(self, x):
heapq.heappush(self.h, MaxHeapObj(x))
def heappop(self):
return heapq.heappop(self.h).val
def peek(self):
return heapq.nsmallest(1, self.h)[0].val
def __getitem__(self, i):
return self.h[i].val
class Point():
def __init__(self, x, y):
self.distance = round(sqrt(x**2 + y**2), 3)
self.coordinates = (x, y)
def find_k_closest(points, k):
res = [Point(x, y) for (x, y) in points]
maxh = MaxHeap()
for i in range(k):
maxh.heappush(res[i])
for p in res[k:]:
if p.distance < maxh.peek():
maxh.heappop()
maxh.heappush(p)
res = [str(x.coordinates) for x in maxh.h]
print(f"{k} closest points from origin : {', '.join(res)}")
points = [(10, 8), (-2, 4), (0, -2), (-1, 0), (3, 5), (-2, 3), (3, 2), (0, 1)]
find_k_closest(points, 3)
विस्तृत करने के लिए Https://stackoverflow.com/a/59311063/1328979 बताने के लिए , यहां सामान्य मामले के लिए पूरी तरह से प्रलेखित, एनोटेट और परीक्षित 3 कार्यान्वयन है।
from __future__ import annotations # To allow "MinHeap.push -> MinHeap:"
from typing import Generic, List, Optional, TypeVar
from heapq import heapify, heappop, heappush, heapreplace
T = TypeVar('T')
class MinHeap(Generic[T]):
'''
MinHeap provides a nicer API around heapq's functionality.
As it is a minimum heap, the first element of the heap is always the
smallest.
>>> h = MinHeap([3, 1, 4, 2])
>>> h[0]
1
>>> h.peek()
1
>>> h.push(5) # N.B.: the array isn't always fully sorted.
[1, 2, 4, 3, 5]
>>> h.pop()
1
>>> h.pop()
2
>>> h.pop()
3
>>> h.push(3).push(2)
[2, 3, 4, 5]
>>> h.replace(1)
2
>>> h
[1, 3, 4, 5]
'''
def __init__(self, array: Optional[List[T]] = None):
if array is None:
array = []
heapify(array)
self.h = array
def push(self, x: T) -> MinHeap:
heappush(self.h, x)
return self # To allow chaining operations.
def peek(self) -> T:
return self.h[0]
def pop(self) -> T:
return heappop(self.h)
def replace(self, x: T) -> T:
return heapreplace(self.h, x)
def __getitem__(self, i) -> T:
return self.h[i]
def __len__(self) -> int:
return len(self.h)
def __str__(self) -> str:
return str(self.h)
def __repr__(self) -> str:
return str(self.h)
class Reverse(Generic[T]):
'''
Wrap around the provided object, reversing the comparison operators.
>>> 1 < 2
True
>>> Reverse(1) < Reverse(2)
False
>>> Reverse(2) < Reverse(1)
True
>>> Reverse(1) <= Reverse(2)
False
>>> Reverse(2) <= Reverse(1)
True
>>> Reverse(2) <= Reverse(2)
True
>>> Reverse(1) == Reverse(1)
True
>>> Reverse(2) > Reverse(1)
False
>>> Reverse(1) > Reverse(2)
True
>>> Reverse(2) >= Reverse(1)
False
>>> Reverse(1) >= Reverse(2)
True
>>> Reverse(1)
1
'''
def __init__(self, x: T) -> None:
self.x = x
def __lt__(self, other: Reverse) -> bool:
return other.x.__lt__(self.x)
def __le__(self, other: Reverse) -> bool:
return other.x.__le__(self.x)
def __eq__(self, other) -> bool:
return self.x == other.x
def __ne__(self, other: Reverse) -> bool:
return other.x.__ne__(self.x)
def __ge__(self, other: Reverse) -> bool:
return other.x.__ge__(self.x)
def __gt__(self, other: Reverse) -> bool:
return other.x.__gt__(self.x)
def __str__(self):
return str(self.x)
def __repr__(self):
return str(self.x)
class MaxHeap(MinHeap):
'''
MaxHeap provides an implement of a maximum-heap, as heapq does not provide
it. As it is a maximum heap, the first element of the heap is always the
largest. It achieves this by wrapping around elements with Reverse,
which reverses the comparison operations used by heapq.
>>> h = MaxHeap([3, 1, 4, 2])
>>> h[0]
4
>>> h.peek()
4
>>> h.push(5) # N.B.: the array isn't always fully sorted.
[5, 4, 3, 1, 2]
>>> h.pop()
5
>>> h.pop()
4
>>> h.pop()
3
>>> h.pop()
2
>>> h.push(3).push(2).push(4)
[4, 3, 2, 1]
>>> h.replace(1)
4
>>> h
[3, 1, 2, 1]
'''
def __init__(self, array: Optional[List[T]] = None):
if array is not None:
array = [Reverse(x) for x in array] # Wrap with Reverse.
super().__init__(array)
def push(self, x: T) -> MaxHeap:
super().push(Reverse(x))
return self
def peek(self) -> T:
return super().peek().x
def pop(self) -> T:
return super().pop().x
def replace(self, x: T) -> T:
return super().replace(Reverse(x)).x
if __name__ == '__main__':
import doctest
doctest.testmod()
https://gist.github.com/marccarre/577a55850998da02af3d4b7b98152cf4
यह एक सरल MaxHeap
कार्यान्वयन है, जिसके आधार पर heapq
। हालांकि यह केवल संख्यात्मक मूल्यों के साथ काम करता है।
import heapq
from typing import List
class MaxHeap:
def __init__(self):
self.data = []
def top(self):
return -self.data[0]
def push(self, val):
heapq.heappush(self.data, -val)
def pop(self):
return -heapq.heappop(self.data)
उपयोग:
max_heap = MaxHeap()
max_heap.push(3)
max_heap.push(5)
max_heap.push(1)
print(max_heap.top()) # 5