ヒープ データ構造を理解するために、独自のヒープ モジュールを実装しています。それらがどのように機能し、管理されているかは理解していますが、私の実装は、ヒープソートを実行している間、標準の python heapq モジュールよりも大幅に遅くなります (サイズ 100,000 のリストの場合、heapq は 0.6 秒かかりますが、私のコードは 2 秒かかります (元は 2.6 秒でした)。 percDown から len() ステートメントを取り出して長さを渡すことで 2 秒まで短縮できるため、メソッドがそれ自体を呼び出すたびに len を計算する必要がありません) これが私の実装です。
def percDown(lst, start, end, node):
#Moves given node down the heap, starting at index start, until the heap property is
#satisfied (all children must be larger than their parent)
iChild = 2 * start + 1
i = start
# if the node has reached the end of the heap (i.e. no children left),
# return its index (we are done)
if iChild > end - 1:
return start
#if the second child exists and is smaller than the first child, use that child index
#for comparing later
if iChild + 1 < end and lst[iChild + 1] < lst[iChild]:
iChild += 1
#if the smallest child is less than the node, it is the new parent
if lst[iChild] < node:
#move the child to the parent position
lst[start] = lst[iChild]
#continue recursively going through the child nodes of the
# new parent node to find where node is meant to go
i = percDown(lst, iChild, end, node)
return i
popMin: 最小値 (lst[0]) をポップし、ヒープを並べ替えます
def popMin(lst):
length = len(lst)
if (length > 1):
min = lst[0]
ele = lst.pop()
i = percDown(lst, 0, length - 1, ele)
lst[i] = ele
return min
else:
return lst.pop()
heapify: リストをその場でヒープに変換します
def heapify(lst):
iLastParent = math.floor((len(lst) - 1) / 2)
length = len(lst)
while iLastParent >= 0:
ele = lst[iLastParent]
i = percDown(lst, iLastParent, length, lst[iLastParent])
lst[i] = ele
iLastParent -= 1
sort: 上記のメソッドを使用して、指定されたリストをヒープソートします (インプレースではありません)。
def sort(lst):
result = []
heap.heapify(lst)
length = len(lst)
for z in range(0, length):
result.append(heap.popMin(lst))
return result
アルゴリズム/ヒープの作成に誤って複雑さを追加しましたか、それとも python heapq モジュールが大幅に最適化されているだけですか? 0.6 秒と 2 秒では大きな違いがあるので、前者だと思います。