亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么我的 Python 腳本在我的 HeapSort 實現上運行得比它應該慢?

為什么我的 Python 腳本在我的 HeapSort 實現上運行得比它應該慢?

慕娘9325324 2021-12-17 15:41:41
我得到了在 Python 或 Java(或任何其他語言)中實現堆排序算法的任務。因為我在 Python 或 Java 方面并不是那么“流利”,所以我決定兩者都做。但在這里我遇到了一個問題,程序的運行時間比它“應該”的要高得多。我的意思是,堆排序應該運行到 O(n * log n) 并且對于在幾個 GHz 的時鐘頻率上運行的當前處理器我沒想到該算法會運行超過 2000 秒的數組大小為 320k因此,對于我所做的,我從 Python 和 Java 中的此類偽代碼實現了算法(我還嘗試了 Rosetta Code 中的 Julia 中的代碼,以查看運行時間是否相似,為什么是 Julia?隨機選擇)所以我檢查了小輸入大小問題的輸出,例如大小為 10、20 和 30 的數組。它似乎在兩種語言/實現中正確排序的數組。然后我使用實現相同算法的 heapq 庫再次檢查運行時間是否相似。當實際情況確實如此時,它讓我感到驚訝……但經過幾次嘗試后,我嘗試了最后一件事,即更新 Python,然后,使用 heapq 的程序比以前的程序運行得快得多。實際上,320k 陣列大約需要 2k 秒,現在大約為 1.5 秒左右。我重試了我的算法,問題仍然存在。所以這里是我實現的 Heapsort 類:class MaxHeap:    heap = []    def __init__(self, data=None):        if data is not None:            self.buildMaxHeap(data)    @classmethod    def toString(cls):        return str(cls.heap)    @classmethod    def add(cls, elem):        cls.heap.insert(len(cls.heap), elem)        cls.buildMaxHeap(cls.heap)    @classmethod    def remove(cls, elem):        try:            cls.heap.pop(cls.heap.index(elem))        except ValueError:            print("The value you tried to remove is not in the heap")    @classmethod    def maxHeapify(cls, heap, i):        left = 2 * i + 1        right = 2 * i + 2        largest = i        n = len(heap)        if left < n and heap[left] > heap[largest]:            largest = left        if right < n and heap[right] > heap[largest]:            largest = right        if largest != i:            heap[i], heap[largest] = heap[largest], heap[i]            cls.maxHeapify(heap, largest)    @classmethod    def buildMaxHeap(cls, heap):        for i in range(len(heap) // 2, -1, -1):            cls.maxHeapify(heap, i)        cls.heap = heap    @staticmethod    def heapSort(table):        heap = MaxHeap(table)        output = []如果您需要其余的代碼來查看錯誤可能在哪里,請不要猶豫,我會提供它。只是不想無緣無故地共享整個文件。如前所述,我預期的運行時間來自最壞情況下的運行時間:O(n * log n) 使用現代架構和 2.6GHz 的處理器我希望大約 1 秒或更短的時間(因為運行時間以納秒為單位詢問)我想即使是 1 秒也太長了)
查看完整描述

1 回答

?
楊__羊羊

TA貢獻1943條經驗 獲得超7個贊

有趣的是,您發布了計算機的時鐘速度 - 您可以計算算法所需的實際步驟數……但是您需要對實現有很多了解。例如,在 python 中,每次創建對象或超出范圍時,解釋器都會更新底層對象上的計數器,如果這些 ref 計數達到 0,則釋放內存。相反,您應該查看相對速度。

您發布的第三方示例顯示,當輸入數組長度加倍時,速度小于加倍。好像不太對吧?事實證明,對于這些示例,構建數組的初始工作可能支配了對數組進行排序所花費的時間!

在您的代碼中,已經有一條注釋指出了我要說的內容...

heap.remove(heap.heap[i]) 此操作將遍歷您的列表(從索引 0 開始)尋找匹配的值,然后將其刪除。這已經很糟糕了(如果它按預期工作,如果您的代碼按預期工作,您將在該行上進行 320k 比較?。5闆r更糟——從數組中刪除一個對象不是就地修改——刪除對象后的每個對象都必須在列表中向前移動。最后,不能保證您確實刪除了那里的最后一個對象……可能存在重復值!

這是一個有用的網站,列出了 python 中各種操作的復雜性 - https://wiki.python.org/moin/TimeComplexity。為了盡可能高效地實現算法,您需要盡可能多的數據結構操作為 O(1)。這是一個例子......這是一些原始代碼,大概是heap.heap是一個列表......

        output = [heap.heap[i]] + output
        heap.remove(heap.heap[i])

正在做

        output.append(heap.heap.pop())

將避免分配新列表并使用恒定時間操作來改變舊列表。(向后使用輸出比使用 O(n) 時間 insert(0) 方法要好得多!如果您確實需要訂單,您可以使用出隊對象進行輸出以獲得 appendleft 方法)

如果您發布了整個代碼,那么我們可能會提供很多其他的小東西。希望這有幫助!


查看完整回答
反對 回復 2021-12-17
  • 1 回答
  • 0 關注
  • 173 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號