Разве Python heapify () не подходит для понимания списка и нарезки? - PullRequest
3 голосов
/ 26 июня 2009

Я обнаружил интересную ошибку в программе, которую реализовал несколько лениво, и подумал, правильно ли я ее понимаю.Короткая версия состоит в том, что Реализация heapq в Python на самом деле не упорядочивает список, а просто обрабатывает список кучи.В частности, я ожидал, что heapify() приведет к упорядоченному списку, который упростит понимание списка упорядоченным образом.

Использование примера приоритетного вызова, как в документации Python:

from heapq import heapify, heappush, heappop
from random import shuffle

class Item(object):
    def __init__(self, name):
        self.name = name

lst = []

# iterate over a pseudo-random list of unique numbers
for i in sample(range(100), 15):
    it = Item("Some name for %i" % i)
    heappush(lst, (i, it))

print([i[0] for i in lst])

В результате мы получим

>>> [2, 22, 7, 69, 32, 40, 10, 97, 89, 33, 45, 51, 94, 27, 67]

. Это, как мы отмечаем, не оригинальное упорядочение списка , а, по-видимому, некоторое упорядочение по центру кучи, как описано здесь .Я лениво ожидал, что это будет полностью упорядочено.

В качестве теста, запуск списка через heapify () не даст никаких изменений (так как список уже упорядочен в куче):

heapify(lst)

print([i[0] for i in lst])

>>> [2, 22, 7, 69, 32, 40, 10, 97, 89, 33, 45, 51, 94, 27, 67]

В то время как итерация по списку с помощью функции heappop() приводит к упорядочению, как и ожидалось:

lst2 = []
while lst: lst2.append(heappop(lst))

print([i[0] for i in lst2])

>>> [2, 7, 10, 22, 27, 32, 33, 40, 45, 51, 67, 69, 89, 94, 97]

Итак, heapq не упорядочивает список (по крайней мере, в человеческом смыслеслово), но скорее функции heappush() и heappop() способны вывести упорядоченный список в кучу.

Результат: любые операции срезов и обработки списка в heapified списке приведут кнеупорядоченные результаты.

Это правда, и это всегда верно?

(КСТАТИ: Python 3.0.1 в системе WinXP)

Ответы [ 4 ]

8 голосов
/ 26 июня 2009

Куча - это не отсортированный список (это представление частично отсортированного двоичного дерева).

Так что да, вы правы, если вы ожидаете, что список с кучей будет вести себя как отсортированный список, вы будете разочарованы. Единственное предположение сортировки, которое вы можете сделать для кучи, это то, что heap[0] всегда является его наименьшим элементом.

(Сложно добавить многое к тому, что вы уже написали - ваш вопрос - отличная статья о том, как обстоят дела. 8 -)

0 голосов
/ 26 июня 2009

"Результат: любые операции по нарезке и списку в кучанном списке приведут к неупорядоченным результатам. Это правда, и всегда ли это правда?" Нет, это не всегда так. Хотя в большинстве случаев он будет не заказан, его можно заказать. heapify () создает список, который удовлетворяет «инварианту кучи». В данном случае это минимальная куча. Оказывается, отсортированный список также удовлетворяет инварианту кучи (см. heapq параграф 4: "heap.sort () поддерживает инвариант кучи"). Таким образом, теоретически возможно, что отсортированный список также будет отсортирован.

0 голосов
/ 26 июня 2009

"" "Я ожидал, что heapify () приведет к упорядоченному списку, который упростит понимание списка упорядоченным способом." "": Если это ожидание основывалось на чтении руководства, вы должны получить отчет об ошибке в документации .

"" "Результат: Любые операции нарезки и обработки списков в heapified списке приведут к неупорядоченным результатам. Это правда, и всегда ли это правда?" "": Так же, как, например, random.shuffle (), указанное действие не определено для получения «упорядоченных» результатов. Он может время от времени давать "упорядоченные" результаты, но это случайно, на него нельзя полагаться и не стоит спрашивать (ИМХО).

0 голосов
/ 26 июня 2009

Результат: любая нарезка и список операции понимания на список в куче даст неупорядоченный Результаты.

Это правда, и всегда ли это правда?

Если вы просто хотите получить одноразовый отсортированный список, используйте:

myList.sort()

Приоритетные очереди / кучи могут использоваться для реализации сортировки или для сохранения очереди в приоритетной форме. Вставки в кучу - это O (LG N), получение - O (1), а удаления - O (LG N), что намного лучше, чем просто повторять весь список снова и снова.

...