A generic priority queue for Python

后端 未结 12 472
面向向阳花
面向向阳花 2020-12-13 03:27

I need to use a priority queue in my Python code, and:

  • am looking for any fast implementations for priority queues
  • optimally, I\'d li
12条回答
  •  不思量自难忘°
    2020-12-13 04:05

    If you want to keep an entire list ordered, not just the top value, I've used some variation of this code in multiple projects, it's a drop in replacement for the standard list class with a similar api:

    import bisect
    
    class OrderedList(list):
        """Keep a list sorted as you append or extend it
    
        An ordered list, this sorts items from smallest to largest using key, so
        if you want MaxQueue like functionality use negative values: .pop(-1) and
        if you want MinQueue like functionality use positive values: .pop(0)
        """
        def __init__(self, iterable=None, key=None):
            if key:
                self.key = key
            self._keys = []
            super(OrderedList, self).__init__()
            if iterable:
                for x in iterable:
                    self.append(x)
    
        def key(self, x):
            return x
    
        def append(self, x):
            k = self.key(x)
            # https://docs.python.org/3/library/bisect.html#bisect.bisect_right
            i = bisect.bisect_right(self._keys, k)
            if i is None:
                super(OrderedList, self).append((self.key(x), x))
                self._keys.append(k)
            else:
                super(OrderedList, self).insert(i, (self.key(x), x))
                self._keys.insert(i, k)
    
        def extend(self, iterable):
            for x in iterable:
                self.append(x)
    
        def remove(self, x):
            k = self.key(x)
            self._keys.remove(k)
            super(OrderedList, self).remove((k, x))
    
        def pop(self, i=-1):
            self._keys.pop(i)
            return super(OrderedList, self).pop(i)[-1]
    
        def clear(self):
            super(OrderedList, self).clear()
            self._keys.clear()
    
        def __iter__(self):
            for x in super(OrderedList, self).__iter__():
                yield x[-1]
    
        def __getitem__(self, i):
            return super(OrderedList, self).__getitem__(i)[-1]
    
        def insert(self, i, x):
            raise NotImplementedError()
        def __setitem__(self, x):
            raise NotImplementedError()
        def reverse(self):
            raise NotImplementedError()
        def sort(self):
            raise NotImplementedError()
    

    It can handle tuples like (priority, value) by default but you can also customize it like this:

    class Val(object):
        def __init__(self, priority, val):
            self.priority = priority
            self.val = val
    
    h = OrderedList(key=lambda x: x.priority)
    
    h.append(Val(100, "foo"))
    h.append(Val(10, "bar"))
    h.append(Val(200, "che"))
    
    print(h[0].val) # "bar"
    print(h[-1].val) # "che"
    

提交回复
热议问题