পাইথনে সর্বাধিক-হ্যাপ প্রয়োগের জন্য আমি কী ব্যবহার করব?


226

পাইথন হ'ল মিনি-হ্যাপগুলির জন্য হ্যাপক মডিউলটি অন্তর্ভুক্ত করে তবে আমার একটি সর্বোচ্চ গাদা প্রয়োজন। পাইথনে সর্বাধিক গাদা প্রয়োগের জন্য আমার কী ব্যবহার করা উচিত?

উত্তর:


241

সবচেয়ে সহজ উপায় হ'ল কীগুলির মানটি উল্টে দেওয়া এবং হ্যাপিক ব্যবহার করা। উদাহরণস্বরূপ, 1000.0 -1000.0 এবং 5.0 -5.0 এ রূপান্তর করুন।


37
এটি স্ট্যান্ডার্ড সমাধানও।
অ্যান্ড্রু ম্যাকগ্রিগোর

43
uggh; মোট ক্লেজ আমি বিস্মিত heapqএকটি বিপরীত সরবরাহ করে না।
shabbychef

40
কি দারুন. আমি অবাক হয়েছি যে এটি সরবরাহ করে না heapq, এবং কোনও ভাল বিকল্প নেই।
ire_and_curses

23
@ গ্যাটোয়াটিগ্রাডো: আপনার যদি এমন কিছু থাকে যা সহজেই int/ এ ম্যাপ করে না float, আপনি একটি বিবর্তিত __lt__অপারেটর দিয়ে একটি শ্রেণিতে মোড়ক দিয়ে ক্রমটিকে বিপরীত করতে পারেন ।
ড্যানিয়েল স্টুটজবাচ

5
@ অ্যারোভিস্টেই একই পরামর্শ প্রযোজ্য: ইতিবাচক বা নেতিবাচক থেকে শুরু না করেই মানগুলি উল্টান (অর্থাত্ সাইনটি স্যুইচ করুন)।
ডেনিস

233

তুমি ব্যবহার করতে পার

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

34
দেখে মনে হচ্ছে সর্বোচ্চ গাদা জন্য কিছু অনথিভুক্ত ফাংশন আছে: _heapify_max, _heappushpop_max, _siftdown_max, এবং _siftup_max
জিয়ুয়াং

127
কি দারুন. আমি বিস্মিত যে IS যেমন একটি বিল্ট-ইন heapq মধ্যে সমাধান। কিন্তু তারপর এটি সম্পূর্ণই হয় অযৌক্তিক এটি করা হয় না এমনকি সামান্য সরকারী নথিতে এ সব আসামি বলেছে! ডব্লিউটিএফ!
রায়লুও

27
যে কোনও পপ / পুশ ফাংশন সর্বাধিক হিপ কাঠামোকে ভেঙে দেয়, সুতরাং এই পদ্ধতিটি সম্ভব নয়।
সিদ্ধার্থ

22
এটা ব্যবহার করোনা. লিনমা এবং সিদ্ধার্থ লক্ষ্য করার সাথে সাথে ধাক্কা / পপ ক্রমটি ভেঙে দেয়।
অ্যালেক্স ফেদুলভ

13
আন্ডারস্কোর দিয়ে শুরু হওয়া পদ্ধতিগুলি ব্যক্তিগত এবং পূর্ব নোটিশ ছাড়াই সরানো যেতে পারে । এগুলি ব্যবহার করবেন না।
ব্যবহারকারী 4815162342

66

সমাধানটি হ'ল আপনার মানগুলিকে হিটে সংরক্ষণ করার সময় তা প্রত্যাখ্যান করা বা আপনার সামগ্রীর তুলনাটি এর মতো করে উল্টানো:

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

তবে আপনাকে আপনার মানগুলি মোড়ানো এবং আন-মোড়ানো মনে রাখতে হবে, যার জন্য এটি জানা দরকার যে আপনি কোনও ন্যূনতম বা সর্বাধিক apাল নিয়ে কাজ করছেন কিনা knowing

মিনহ্যাপ, ম্যাক্সহীপ ক্লাস

জন্য ক্লাস 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__ এ alচ্ছিক প্যারামিটার যুক্ত করেছি যে ক্ষেত্রে আমি কল করি heapq.heapifyএবং একটি heapreplaceপদ্ধতি যুক্ত করেছি।
বুবু

1
অবাক হলেন যে কেউ এই টাইপটি ধরেনি Max অন্যথায়, সত্যিই একটি খুব পরিষ্কার সমাধান।
চিরাজ বেনআবেডেলকাডার

@ চিরজবেন আবেদেলকাদার স্থির করেছেন, আপনাকে ধন্যবাদ
আইজাক টার্নার

39

সবচেয়ে সহজ এবং আদর্শ সমাধান

-1 দ্বারা মানগুলি গুণ করুন

এই নাও. সমস্ত সর্বোচ্চ সংখ্যা এখন সর্বনিম্ন এবং বিপরীতে।

কেবল মনে রাখবেন যে আপনি যখন আসল মানটি পেতে আবার কোনও মৌলিকটিকে -1 দিয়ে গুণাবেন তখন পপ করবেন।


দুর্দান্ত, তবে বেশিরভাগ সমাধান ক্লাস / অন্যান্য ধরণের সমর্থন করে এবং প্রকৃত ডেটা পরিবর্তন করে না। উন্মুক্ত প্রশ্নটি হ'ল যদি -1 দ্বারা গুণিত মানগুলি তাদের পরিবর্তন করে না (অত্যন্ত সুনির্দিষ্ট ভাসা)।
অ্যালেক্স বারানোভস্কি

1
@AlexBaranowski। এটি সত্য, তবে এটি রক্ষণাবেক্ষণকারীদের কাছ থেকে প্রতিক্রিয়া ছিল: bugs.python.org/issue27295
ফ্লেয়ার

ভাল রক্ষণাবেক্ষণকারীদের কিছু কার্যকারিতা বাস্তবায়ন না করার অধিকার রয়েছে, তবে এটি একটি আইএমও আসলে কার্যকর।
অ্যালেক্স বারানোভস্কি

7

আমি হিপকের সর্বোচ্চ হ্যাপ সংস্করণটি প্রয়োগ করেছি এবং এটি পিপিআইতে জমা দিয়েছি submitted (হিপকিউ মডিউল সিপিথন কোডের খুব সামান্য পরিবর্তন))

https://pypi.python.org/pypi/heapq_max/

https://github.com/he-zhe/heapq_max

স্থাপন

pip install heapq_max

ব্যবহার

tl; dr: সমস্ত ফাংশনে '_ম্যাক্স' যোগ করা ছাড়া হ্যাপাক মডিউলটির সমান।

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

4

আপনি যদি তুলনীয় তবে অন্তর্-মত নয় এমন কীগুলি সন্নিবেশ করিয়ে রাখছেন তবে আপনি তাদের তুলনা অপারেটরদের (যেমন <= হয়ে>>>> <=) হয়ে যেতে পারেন। অন্যথায়, আপনি heapq._sipup টি heapq মডিউলটিতে ওভাররাইড করতে পারেন (এটি শেষ পর্যন্ত কেবলমাত্র পাইথন কোড)।


9
"এটি কেবলমাত্র পাইথন কোড": এটি আপনার পাইথন সংস্করণ এবং ইনস্টলেশনের উপর নির্ভর করে। উদাহরণস্বরূপ, আমার ইনস্টল করা heapq.py এর 309 ( # If available, use C implementation) লাইনের পরে কিছু কোড রয়েছে যা মন্তব্যটি বর্ণনা করে ঠিক তেমন করে।
tzot

3

আপনাকে বৃহত্তম বা ক্ষুদ্রতম আইটেমগুলির একটি স্বেচ্ছাসেবী চয়ন করতে মঞ্জুরি দেওয়া

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]

3
একটি ব্যাখ্যা ক্রম হবে।
পিটার মর্টেনসেন

আমার শিরোনামটি আমার ব্যাখ্যা
জেসনলোনহার্ড

1
আমার উত্তর প্রশ্নের চেয়ে দীর্ঘ। আপনি কী ব্যাখ্যা যুক্ত করতে চান?
জেসনলোনহার্ড

উইকিপিডিয়া. org/wiki/Min-max_heap এবং docs.python.org/3.0/library/heapq.html এছাড়াও কিছুটা সহায়ক হতে পারে।
জেসনলোনহার্ড

2
এটি সঠিক ফলাফল দেয় কিন্তু এটি কার্যকর করার জন্য আসলে একটি গাদা ব্যবহার করে না। দস্তাবেজটি উল্লেখ করেছে যে প্রতিবার তালিকাটিকে বৃহত্তর এবং সবচেয়ে ছোট আকারে সাজান।
রসফ্যাব্রিকেন্ট

3

ইন ক্লাস প্রসারিত করা এবং __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()

এটি সম্ভব, তবে আমার মনে হচ্ছে এটি জিনিসগুলিকে অনেক ধীরে ধীরে কমিয়ে দেবে এবং প্রচুর অতিরিক্ত স্মৃতি ব্যবহার করবে। MyInt সত্যিই হিপ কাঠামোর বাইরে ব্যবহার করা যাবে না। তবে একটি উদাহরণ টাইপ করার জন্য আপনাকে ধন্যবাদ, এটি দেখতে আকর্ষণীয়।
লিও উফিম্টসেভ

Hah! আমি মন্তব্য করার একদিন পরে আমি এমন পরিস্থিতিতে পৌঁছে গেলাম যেখানে আমাকে কাস্টম অবজেক্টটি একটি গাদা করার দরকার ছিল এবং সর্বোচ্চ গাদা দরকার ছিল। আমি প্রকৃতপক্ষে এই পোস্টটিকে আবার গুগল করেছিলাম এবং আপনার উত্তর খুঁজে পেয়েছি এবং আমার সমাধানটি এটিকে বন্ধ করে দিয়েছি। ( কেন্দ্র থেকে দূরত্বের তুলনায় x, y স্থানাঙ্ক এবং এলটি ওভাররাইড সহ একটি পয়েন্ট হ'ল কাস্টম অবজেক্ট )। এই পোস্ট করার জন্য আপনাকে ধন্যবাদ, আমি upvated!
লিও উফিম্টসেভ

1

আমি একটি হিপ র‍্যাপার তৈরি করেছি যা সর্বাধিক হিপ তৈরির মানগুলিকে উল্টে দেয়, পাশাপাশি লাইব্রেরিকে আরও OOP- এর মতো করে তুলতে একটি মিনি-হ্যাপের জন্য একটি মোড়কের ক্লাস। এখানে সংক্ষেপে বলা হয়েছে। এখানে তিনটি শ্রেণি রয়েছে; হিপ (বিমূর্ত শ্রেণি), হিপমিন এবং হিপম্যাক্স।

পদ্ধতি:

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

0

আপনি যদি সর্বোচ্চ হিপ ব্যবহার করে বৃহত্তম কে উপাদান পেতে চান তবে আপনি নিম্নলিখিত কৌশলটি করতে পারেন:

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]

1
দুর্ভাগ্যক্রমে, এর জন্য সময় জটিলতা হ'ল ও (ম্লগএম) যেখানে এম = লেন (নামস), যা হ্যাপকের উদ্দেশ্যকে পরাস্ত করে। এর জন্য বাস্তবায়ন এবং মন্তব্যগুলি দেখুন nlargest-> github.com/python/cpython/blob/…
আর্থার এস

1
আপনার তথ্যবহুল মন্তব্যের জন্য আপনাকে ধন্যবাদ, সংযুক্ত লিঙ্কটি চেক করতে নিশ্চিত করবে।
রোয়ানএক্স

0

আইজ্যাক টার্নারের দুর্দান্ত উত্তরের অনুসরণ করে , আমি সর্বোচ্চ হিপ ব্যবহার করে উত্সকে কে ক্লোজস্ট পয়েন্টের উপর ভিত্তি করে একটি উদাহরণ রাখতে চাই ।

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)

0

বিস্তারিত বলতে 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


0

এটি 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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.