前言
對于正準備閱讀本書的讀者,我希望你已經有一些編程語言(例如Python)的基礎;如果你之前從來沒有接觸過編程,建議首先學習一門編程語言,然后進行本書的學習!我在本書中使用了Python,因為它對程序員和初學者來說都很容易使用。
算法的目標是解決軟件應用程序中經常出現的問題。為大學生講授算法時,我試圖在學生的背景知識和我所講授的算法概念之間架起一座橋梁。許多教科書雖然編寫得非常精美,但在算法解釋方面還是太過簡單。如果沒有一份指南向學生解釋如何瀏覽算法材料,學生們常常無法自學算法。
我將通過一段文字和圖P-1來說明本書的目標。我將介紹一些數據結構,并解釋如何使用基本的固定長度的數據類型(例如32位的整型或64位的浮點型)對數據進行組織。有些算法,例如二分數組搜索,是直接在數據結構上工作的。更復雜的算法,尤其是圖的算法,依賴于一些基本的抽象數據類型。對于抽象數據類型,我會在必要的時候進行介紹,例如堆棧或優先隊列。這些數據結構提供了基本操作,可以通過選擇正確的數據結構來高效實現。在本書的最后,我將帶領讀者理解各種不同的算法是如何實現它們的性能的。對于這些算法,我要么用Python展示完整的實現,要么介紹提供了高效實現的第三方Python程序包。
在本書所提供的相關代碼資源中,讀者將會看到每一章都有一個名為book.py的Python文件,執行這個文件能夠生成書中的所有表格。

圖P-1 本書技術內容的總結
在本書第1~7章的章末有挑戰練習,為讀者提供測試自己所學習的新知識的機會。我希望讀者在查看我所提供的示例解決方案之前嘗試自己完成這些練習。我所提供的解決方案可以在本書配套的代碼庫中找到。
本書的所有代碼都可以在相關聯的GitHub代碼庫http://github.com/heineman/ LearningAlgorithms中找到。這些代碼兼容了Python 3.4或更高版本。在相關的時候,我將遵循 Python 的典型做法,使用雙下畫線方法,例如__str()__
和__len()__
。在本書的代碼實例中,我使用了兩個空格的縮進以減少代碼占據頁面的寬度,而在代碼庫中使用了標準的4個空格的縮進。在一些代碼清單中,我采用了簡潔的單行代碼格式,例如if j == lo:break
這樣的if
語句。
本書的代碼使用了3個外部的、開放源代碼的Python程序庫,具體如下。
● NumPy 1.19.5。
● SciPy 1.6.0。
● NetworkX 2.5。
NumPy和SciPy都是極為常見的開源Python程序庫,具有極廣泛的用戶。我使用這兩個程序庫對算法的運行時間性能進行分析。NetworkX提供了許多適用于圖的不同高效算法(詳見第7章),它還提供了一種可以直接使用的圖數據結構的實現。這些程序庫使我不必“事必躬親”。如果讀者沒有安裝這些程序庫,也不會有什么問題,因為我提供了一些應急措施。
本書使用timeit
模塊所生成的所有計時結果都是通過反復運行代碼片段所得的。代碼片段常常需要重復運行多次,以保證它所測量的時間是正確的。在運行一定的次數之后,最短的時間(而不是所有運行時間的平均值)被當作運行時間性能。這通常被認為是生成準確計時方案的有效方式,因為多次運行的平均時間在運行受到外部影響(例如操作系統所執行的其他任務)時會影響計時結果。
當一種算法(例如第5章的插入排序)的性能對它的輸入高度敏感時,我將會清楚地說明采用所有計時結果的平均時間。
本書的代碼庫所包含的Python代碼超過10,000行,讀者可以通過腳本執行本書中的所有測試用例并計算書中的所有表格數據。本書的許多圖表可以重新生成。本書的代碼按照Python的Docstring約定進行文檔說明,代碼的覆蓋率使用Coverage.py網站檢驗達到了95%。
如果讀者發現技術問題,或者在使用代碼示例時遇到問題,可以通過異步社區中的本書頁面與我們聯系。
本書是為了幫助讀者更好地完成工作。一般而言,對于本書所提供的示例代碼,讀者可以在自己的程序和文檔中使用它們,并不需要聯系我們以獲得許可,除非讀者復制了大塊的代碼。例如,在編寫程序時使用了本書的幾段代碼并不需要許可,但是,銷售或發布O’Reilly圖書的示例代碼需要得到我們的許可;引用本書以及書中的示例代碼并不需要獲得許可,但是把本書的大量示例代碼復制到自己產品的文檔中需要獲得許可。
我們贊賞注明出處,但一般情況下并不要求。出處注明通常包括書名、作者、出版商和ISBN。例如,《算法學習指南》(Learning Algorithms: A Programmer’s Guide to Writing Better Code),作者George Heineman(O’Reilly)。
如果讀者覺得自己對本書的示例代碼的使用超出了正常范圍或者超出上面的許可,可以通過permissions@oreilly.com與我們聯系。
下面是本書所采用的印刷約定。
黑體:表示新的術語及我想要強調的要點。
等寬字體:在程序清單中使用,也用于在段落中表示程序內容,例如變量或函數名、數據類型和關鍵字。
這種由環尾狐猴所提示的內容是提示或建議。我使用這幅圖像的原因是環尾狐猴的聯合視野最大可達280°,大于一般的靈長類動物(例如人類)。當出現這個提示圖標時,我一般要求讀者拓寬自己的視野,去了解一個新的概念或一個新的Python功能。
這種由烏鴉所提示的內容為基本的備注。大量的科研人員發現烏鴉是非常聰明的,是一種能夠解決問題的動物,有些烏鴉甚至能夠使用工具。我使用這一圖標來表示定義新術語或向讀者展示一個實用概念,讀者在閱讀接下來的內容之前應該理解這個術語或實用概念。
這種由蝎子所提示的內容為警告。我使用蝎子圖標來提醒讀者在應用算法時必須處理的關鍵挑戰。

近40年來,O’Reilly Media致力于提供技術和商業培訓、知識和卓越見解,來幫助眾多公司取得成功。
我們擁有獨一無二的專家和革新者組成的龐大網絡,他們通過圖書、文章、會議和我們的在線學習平臺分享知識和經驗。O’Reilly的在線學習平臺允許你按需訪問現場培訓課程、深入的學習路徑、交互式編程環境,以及O’Reilly和200多家其他出版商提供的大量文本和視頻資源。更多相關信息請訪問http://oreilly.com。
如果讀者對本書有任何的評論或疑問,可以與出版社聯系。
美國:
O’Reilly Media, Inc.
1005 Gravenstein Highway North
Sebastopol, CA 95472
中國:
北京市西城區西直門南大街2號成銘大廈C座807室(100035)
奧萊利技術咨詢(北京)有限公司
我們為本書提供了一個網頁,其中包含勘誤表、示例和其他的額外信息,讀者可以通過https://oreil.ly/learn-algorithms進行訪問。
如果你對本書有什么評論或技術上的建議,請發送電子郵件到 bookquestions@oreilly.com。
關于我們的圖片和課程的新聞和信息,可以訪問http://oreilly.com。
我認為,算法的研究是計算機科學最精華的部分。感謝讀者給我機會展示本書的內容。我還想感謝我的妻子Jennifer,感謝她在本書以及我的另一本著作的編寫過程中所給予的支持。感謝我的兩個兒子Nicholas和Alexander,他們現在已經長大,已經可以開始學習編程了。
感謝O’Reilly的編輯Melissa Duffield、Sarah Grey、Beth Kelly和Virginia Wilson,感謝他們在組織本書的概念及解釋的過程中對我的幫助,他們的幫助有效地提高了本書的質量。感謝本書的技術審稿人員Laura Helliwell、Charlie Lovering、Helen Scott、Stanley Selkow和Aura Velarde,感謝他們減少了書中的不一致之處,提高了算法實現及其解釋的質量。如果書中還存在任何缺陷,那肯定都是我自己的責任。