當前位置:首頁 » 編程語言 » pythonheapq

pythonheapq

發布時間: 2023-06-14 04:50:02

python headq模塊淺析

參考:
heapq Documentation
淺析Python heapq模塊 堆數據結構

在Python中也對堆這種數據結構進行了模塊化,我們可以通過調用heapq模塊來建立堆這種數據結構,同時heapq模塊也提供了相應的方法來對堆做操作。

heap = [] #創建了一個空堆

item = heap[0] #查看堆中最小值,不彈出

heappush(heap,item) #往堆中插入一條新的值

item = heappop(heap) #從堆中彈出最小值, 如果堆為空報 IndexError 異常

heappushpop() #1.將值插入到堆中 2.彈出堆中的最小值。
P.S. 1. 可以保證彈出最小元素 2. 效率比先heappush再heappop快

heapify(x) #以線性時間講一個列表轉化為堆

item = heapreplace(heap,item) #彈出並返回最小值,然後將heapqreplace方法中item的值插入到堆中,堆的整體結構不會發生改變。如果堆為空報 IndexError 異常。 在需要保證堆大小不變的適合使用
P.S. 1. 彈出的元素可能比加入的item大 2. 效率比先heappop再heappush快

merge(*iterables, key=None, reverse=False) #合並多個堆然後輸出

nlargest(n , iterbale, key=None) #從堆中找出做大的N個數,key的作用和sorted( )方法裡面的key類似,用列表元素的某個屬性和函數作為關鍵字

nsmallest(n, iterable, key=None) #找到堆中最小的N個數用法同上

該段為heapq Documentation里節選的翻譯
堆作為數據結構在內存和二級緩存中充當了重要的角色。優先隊列中也會經常使用堆,這也就給堆數據結構提出了很多挑戰。例如內存中存放了數多個計劃任務的時候我們可以定義一個數列list(priority,task)來保存在堆結構中。但是這樣就出現了很多問題 :
1.排序的穩定性:當任務加入到堆中時,如果兩個任務有同等的優先順序,兩個任務實際上在列表裡是沒什麼區別的,那我怎麼得到返回值?
2.在Python3以後的版本中,如果元組(priority,task)priority是一樣的,而且task沒有一個默認的比較參照值,那這樣我們其實是沒有辦法來比較的。
3.如果一個任務的優先順序發生了改變,那麼我們如何來處理該任務在相應堆中優先順序的變化,堆中位置肯定會改變。
4.如果一個任務因為要等待其他的任務(最簡單的比方,等待父進程)而照成懸掛狀態,我們如何在堆中去找到它並且做相應的操作(降低優先順序或者刪除該任務)

解決前兩個問題的方法我們可以採用三元數組的方法。設置一個優先順序,一個條目值,一個任務值。即使當兩個任務有相同優先順序的時候,因為條目值不一樣可以幫助cpu來裁決它們被載入的順序。
剩下需要解決的問題是如何找到被懸掛而推遲的任務,然後嘗試去修改優先順序或者永久刪除這個任務。我們可以使用字典,來指向堆中某個任務的條目值。
最後就是刪除操作,刪除會改變堆的結構。為了保證堆結構的特性,我們可以標記已有將被刪除的任務的條目值,然後將該任務重新打標加入到堆中。

② 在python中一共有多少個標准庫

Python 語言官方的參考手冊鍾,介紹了與 Python 一同發行的標准庫。

文本處理服務

  • string--- 常見的字元串操作

  • re--- 正則表達式操作

  • difflib--- 計算差異的輔助工具

  • textwrap--- 文本自動換行與填充

  • unicodedata--- Unicode 資料庫

  • stringprep--- 網際網路字元串預備

  • readline--- GNU readline 介面

  • rlcompleter--- GNU readline 的補全函數

二進制數據服務

  • struct--- 將位元組串解讀為打包的二進制數據

  • codecs--- 編解碼器注冊和相關基類

數據類型

  • datetime--- 基本日期和時間類型

  • zoneinfo--- IANA 時區支持

  • calendar--- 日歷相關函數

  • collections--- 容器數據類型

  • collections.abc--- 容器的抽象基類

  • heapq--- 堆隊列演算法

  • bisect--- 數組二分查找演算法

  • array--- 高效的數值數組

  • weakref--- 弱引用

  • types--- 動態類型創建和內置類型名稱

  • --- 淺層 (shallow) 和深層 (deep) 復制操作

  • pprint--- 數據美化輸出

  • reprlib--- 另一種repr()實現

  • enum--- 對枚舉的支持

  • graphlib--- 操作類似圖的結構的功能

數字和數學模塊

  • numbers--- 數字的抽象基類

  • math--- 數學函數

  • cmath--- 關於復數的數學函數

  • decimal--- 十進制定點和浮點運算

  • fractions--- 分數

  • random--- 生成偽隨機數

  • statistics--- 數學統計函數

函數式編程模塊

  • itertools--- 為高效循環而創建迭代器的函數

  • functools--- 高階函數和可調用對象上的操作

  • operator--- 標准運算符替代函數

文件和目錄訪問

  • pathlib--- 面向對象的文件系統路徑

  • os.path--- 常用路徑操作

  • fileinput--- 迭代來自多個輸入流的行

  • stat--- 解析stat()結果

  • filecmp--- 文件及目錄的比較

  • tempfile--- 生成臨時文件和目錄

  • glob--- Unix 風格路徑名模式擴展

  • fnmatch--- Unix 文件名模式匹配

  • linecache--- 隨機讀寫文本行

  • shutil--- 高階文件操作

數據持久化

  • pickle--- Python 對象序列化

  • reg--- 注冊配合pickle模塊使用的函數

  • shelve--- Python 對象持久化

  • marshal--- 內部 Python 對象序列化

  • dbm--- Unix "資料庫" 介面

  • sqlite3--- SQLite 資料庫 DB-API 2.0 介面模塊

數據壓縮和存檔

  • zlib--- 與gzip兼容的壓縮

  • gzip--- 對gzip格式的支持

  • bz2--- 對bzip2壓縮演算法的支持

  • lzma--- 用 LZMA 演算法壓縮

  • zipfile--- 使用ZIP存檔

  • tarfile--- 讀寫tar歸檔文件

文件格式

  • csv--- CSV 文件讀寫

  • configparser--- 配置文件解析器

  • tomllib--- Parse TOML files

  • netrc--- netrc 文件處理

  • plistlib--- 生成與解析 Apple.plist文件

加密服務

  • hashlib--- 安全哈希與消息摘要

  • hmac--- 基於密鑰的消息驗證

  • secrets--- 生成管理密碼的安全隨機數

通用操作系統服務

  • os--- 多種操作系統介面

  • io--- 處理流的核心工具

  • time--- 時間的訪問和轉換

  • argparse--- 命令行選項、參數和子命令解析器

  • getopt--- C 風格的命令行選項解析器

  • logging--- Python 的日誌記錄工具

  • logging.config--- 日誌記錄配置

  • logging.handlers--- 日誌處理程序

  • getpass--- 攜帶型密碼輸入工具

  • curses--- 終端字元單元顯示的處理

  • curses.textpad--- 用於 curses 程序的文本輸入控制項

  • curses.ascii--- 用於 ASCII 字元的工具

  • curses.panel--- curses 的面板棧擴展

  • platform--- 獲取底層平台的標識數據

  • errno--- 標准 errno 系統符號

  • ctypes--- Python 的外部函數庫

並發執行

  • threading--- 基於線程的並行

  • multiprocessing--- 基於進程的並行

  • multiprocessing.shared_memory--- Shared memory for direct access across processes

  • concurrent包

  • concurrent.futures--- 啟動並行任務

  • subprocess--- 子進程管理

  • sched--- 事件調度器

  • queue--- 一個同步的隊列類

  • contextvars--- 上下文變數

  • _thread--- 底層多線程 API

網路和進程間通信

  • asyncio--- 非同步 I/O

  • socket--- 底層網路介面

  • ssl--- 套接字對象的 TLS/SSL 包裝器

  • select--- 等待 I/O 完成

  • selectors--- 高級 I/O 復用庫

  • signal--- 設置非同步事件處理程序

  • mmap--- 內存映射文件支持

互聯網數據處理

  • email--- 電子郵件與 MIME 處理包

  • json--- JSON 編碼和解碼器

  • mailbox--- 操作多種格式的郵箱

  • mimetypes--- 映射文件名到 MIME 類型

  • base64--- Base16, Base32, Base64, Base85 數據編碼

  • binascii--- 二進制和 ASCII 碼互轉

  • quopri--- 編碼與解碼經過 MIME 轉碼的可列印數據

結構化標記處理工具

  • html--- 超文本標記語言支持

  • html.parser--- 簡單的 HTML 和 XHTML 解析器

  • html.entities--- HTML 一般實體的定義

XML處理模塊

  • xml.etree.ElementTree--- ElementTree XML API

  • xml.dom--- 文檔對象模型 API

  • xml.dom.minidom--- 最小化的 DOM 實現

  • xml.dom.pulldom--- 支持構建部分 DOM 樹

  • xml.sax--- 支持 SAX2 解析器

  • xml.sax.handler--- SAX 處理句柄的基類

  • xml.sax.saxutils--- SAX 工具集

  • xml.sax.xmlreader--- 用於 XML 解析器的介面

  • xml.parsers.expat--- 使用 Expat 的快速 XML 解析

互聯網協議和支持

  • webbrowser--- 方便的 Web 瀏覽器控制工具

  • wsgiref--- WSGI 工具和參考實現

  • urllib--- URL 處理模塊

  • urllib.request--- 用於打開 URL 的可擴展庫

  • urllib.response--- urllib 使用的 Response 類

  • urllib.parse用於解析 URL

  • urllib.error--- urllib.request 引發的異常類

  • urllib.robotparser--- robots.txt 語法分析程序

  • http--- HTTP 模塊

  • http.client--- HTTP 協議客戶端

  • ftplib--- FTP 協議客戶端

  • poplib--- POP3 協議客戶端

  • imaplib--- IMAP4 協議客戶端

  • smtplib--- SMTP 協議客戶端

  • uuid---RFC 4122定義的UUID對象

  • socketserver--- 用於網路伺服器的框架

  • http.server--- HTTP 伺服器

  • http.cookies--- HTTP狀態管理

  • http.cookiejar—— HTTP 客戶端的 Cookie 處理

  • xmlrpc--- XMLRPC 服務端與客戶端模塊

  • xmlrpc.client--- XML-RPC 客戶端訪問

  • xmlrpc.server--- 基本 XML-RPC 伺服器

  • ipaddress--- IPv4/IPv6 操作庫

多媒體服務

  • wave--- 讀寫WAV格式文件

  • colorsys--- 顏色系統間的轉換

國際化

  • gettext--- 多語種國際化服務

  • locale--- 國際化服務

程序框架

  • turtle--- 海龜繪圖

  • cmd--- 支持面向行的命令解釋器

  • shlex—— 簡單的詞法分析

  • Tk圖形用戶界面(GUI)

  • tkinter—— Tcl/Tk 的 Python 介面

  • tkinter.colorchooser--- 顏色選擇對話框

  • tkinter.font--- Tkinter 字體封裝

  • Tkinter 對話框

  • tkinter.messagebox--- Tkinter 消息提示

  • tkinter.scrolledtext--- 滾動文字控制項

  • tkinter.dnd--- 拖放操作支持

  • tkinter.ttk--- Tk 風格的控制項

  • tkinter.tix--- TK擴展包

③ python標准庫有哪些

Python標准庫的內容涵蓋了非常多的功能,主要包括文件、字元串和數字處理,數據結構、網路編程、操作系統用戶界面、網頁測試、線程以及其它的工具。
具體有,1、文件操作相關的模塊,os,os。
path,shutil,errno,stat,glob,fnmatch,tempfile等。
2、字元串和文本處理模塊,string,re,difflib和textwrap等。
3、數據結構形式,collections,bisect,array,heapq,queue,struct和weakref等。
4、網路編程與操作系統,SocketServer,socket,selectselectors,threading,multiprocessing,subprocess,mmap,sched,asyncore等。
5、網頁測試,urllib,扮態urllib2,配則httplib,ftplib,gopherlib,spider等。
6、解析和處理XML,HTMLParser,ElementTree,XMLParser,XMLWriter,SAX,minidom,expat等。
7、除此之廳賣源外,還包含一些其他方便實用的部分,如BaseHTTPServer,CGIHTTPServer,Cookie,templating,xmlrpclib,formatter,email等。
此外,Python還支持第三方庫和框架,有很多實用的框架和工具可以讓開發者高效、便捷地完成國家工作。

④ Python高級數據結構——堆

在一個 最小堆 (min heap) 中,如果 P 是 C 的一個父級節點,那麼 P 的 key(或 value) 應小於或等於 C 的對應值。 正因為此,堆頂元素一定是最小的,我們會利用這個特點求最小值或者第 k 小的值。

在一個 最大堆 (max heap) 中,P 的 key(或 value) 大於或等於 C 的對應值。

以python為例,說明堆的幾個常見操作,這里需要用到一個內置的包:heapq

python中使用堆是通過傳入一個數組,然後調用一個函數,在原地讓傳入的數據具備堆的特性

需要注意的是,heapify默認構造的是小頂堆(min heap),如果要構造大頂堆,思路是把所有的數值倒轉,既* -1,例如:

使用heapq提供的函數: heappop 來實現

具體使用方式參考 初始化Heapify

使用heapq提供的函數: heappush 來實現

同時heapq還提供另外一個函數: heappushpop ,能夠在一個函數實現push&pop兩個操作;順序是:先push再pop

根據官方文檔的描述,這個函數會比先在外圍先調用heappush,再調用heappop,效率更高

先pop數據再push數據,和heappushpop的順序是反著的; 同樣的,這樣調用的性能也會比先調用heappop再調用heappush更好

如果pop的時候隊列是空的,會拋出一個異常

可以通過 heapq.merge 將多個 已排序 的輸入合並為一個已排序的輸出,這個本質上不是堆;其實就是用兩個指針迭代

對於這個問題,有一個演算法題可以實現相同的功能

從 iterable 所定義的數據集中返回前 n 個最大/小元素組成的列表。

函數為: heapq.nlargest() | heapq.nsmallest()

heapq - Heap queue algorithm - Python 3.10.4 documentation

⑤ python哪些標准庫

標准庫比較多 功能也不同:
標准庫
sys
系統相關的參數和函數。 sys 庫一般用來訪問和修改系統相關信息,比如查看 python 版本、系統環境變數、模塊信息和 python 解釋器相關信息等等。
os
操作系統介面模塊。這個庫提供了訪問操作系統相關依賴的方式,比如輸入輸出操作、讀寫操作、操作系統異常錯誤信息、進程線程管理、文件管理、調度程序等等。
re
正則表達式操作。這個庫是我喜歡並且經常會用到的庫,在對大量字元串進行處理的時候用正則表達式是最快速有效的方式,但是正則表達式的學習曲線較高,有興趣的朋友可以訪問這個網站學習。
math
數學函數庫。 math 庫提供了對 C 語言標準定義的數學函數訪問,比如數論(Number-theoretic)的各種表示方法、冪和對數函數(Power and logarithmic functions)、三角函數(Trigonometric functions)、常量圓周率(π)和自然常數(e)等等。
random
生成偽隨機數。
偽隨機數與隨機數(真隨機數)不同的是執行環境,隨機數是真實世界中通過物理過程實踐得出結論,而偽隨機數是通過計算機的特定演算法生成的數,所以這個過程是可預測的、有規律的,只是循環周期較長,並不能與現實場景相切合。
random庫提供生成隨機數,可以模擬現實世界中隨機取數、隨機抽獎等等。
logging
日誌記錄工具。這個庫提供了對應用程序和庫函數的日誌記錄,日常開發中我們經常需要通過日誌列印出當前程序的運行狀態,實時查看可能出現的堆棧異常和錯誤信息。
json
Json 編碼和解碼器。 json 庫提供了對 json 數據的支持,日常開發中我們做前後端分離需要對傳輸數據 json 進行序列化和反序列化操作,以保證對數據的完整性和有效性,而序列化和反序列化其實就是編碼和解碼的過程。
pickle
Python 對象序列化庫。 pickle 庫支持對 python 對象進行序列化和反序列化操作,當我們需要將處理好的對象保存到文件或資料庫中時,就可以將其序列化成二進制數據,從而更好的保存起來。
shelve
Python 對象持久化。簡單的數據存儲方案。
socket
底層網路介面。 socket(套接字) 庫提供了標準的BSD(伯克利套接字) Socket API,可以通過訪問底層操作系統 Socket 的相關介面進行網路通訊。
datetime
基本日期和時間類型庫。該庫提供了各種簡單和復雜的方式處理日期和時間,日常我們會用時間測算時間消耗、復雜度,對存儲的創建時間和修改時間也需要進一步說明,對計時器的描述和控制也需要用到該庫。
hashlib
安全哈希和消息摘要。摘要演算法 其實就是對某些數據進行加密(不可逆的加密演算法),因為被加密的數據無法破解,所以就能防止被篡改。常見的摘要演算法有 MD5、SHA1,一般我們會用 MD5 對用戶口令進行加密,防止盜用後被輕易破解;而 SHA1 與 MD5 類似,但是 SHA1 會產生更長的長度,也更安全,但是演算法的復雜性通常伴隨著存儲空間和時間的消耗。要說比SHA1更長的字元長度,還有 SHA224、SHA256、SHA384 和 SHA512,看名字就能知道。
大家都知道無論演算法生成的字元長度如何都有可能發生碰撞(被破解),這是不可避免的,所以具體場景具體情況而定。
configparser
配置文件解析器。 configparser 庫可以輕松定製配置文件,通過解析配置文件的信息我們就可以全局訪問相關配置。
urllib
URL 處理模塊。 urllib 庫集成了處理 URLs(統一資源定位符)的各種模塊:
URL urllib.request URL robots.txt urllib 庫對訪問網路有很好的支持,提供了對數據的訪問和處理、文件的上傳和下載、記錄 cookie 和 session 等等。
itertools
為高效循環而創建迭代器的函數。 itertools 庫也是經常需要用到,當我們要對某些數進行 for-in 時就需要先將其處理成一個可迭代對象,之後我們才能進行遍歷操作。
collections
容器數據類型庫。 collections 庫提供了對所有容器數據類型的支持,包括 dict, list, set 和 tuple。我們可以用此庫對不同數據類型進行操作,常有的函數方法有這些:
namedtuple() 創建命名元組子類的工廠函數 deque 類似列表(list)的容器,實現了在兩端快速添加(append)和彈出(pop) ChainMap 類似字典(dict)的容器類,將多個映射集合到一個視圖裡面 Counter 字典的子類,提供了可哈希對象的計數功能 OrderedDict 字典的子類,保存了他們被添加的順序 defaultdict 字典的子類,提供了一個工廠函數,為字典查詢提供一個默認值 UserDict 封裝了字典對象,簡化了字典子類化 UserList 封裝了列表對象,簡化了列表子類化 UserString 封裝了列表對象,簡化了字元串子類化 functools
高階函數和可調用對象上的操作。該庫主要調用高階函數,是常規函數的一種補充。目前庫中包含以下幾種函數:
cmp_to_key lru_cache total_ordering partial partialmethod rece singledispatch update_wrapper wraps threading
線程並行庫。 threading 庫支持線程和多線程的操作,針對多線程並發的問題可以給數據加同步鎖,一次只能讓一個線程處理數據,從而避免出現數據讀寫混亂。
在 CPython 解釋器上,因為GIL(全局解釋器鎖)鎖機制的存在的,被設計成線程安全,所以同一時間只能執行一個線程,這就導致了多線程不能發揮出計算機的多核特性。
multiprocessing
進程並行庫。 multiprocessing 庫與 threading 庫很類似,不同的是進程庫可以創建子進程避開 GIL,從而彌補線程庫存在的劣勢和發揮計算機的多核特性。
timeit
測量小代碼片段的執行時間。此庫主要用來計算運行代碼的時間消耗,支持多種方式傳入參數。
atexit
退出處理器。當處理一個函數需要立馬退出時可以使用該庫。
abc
抽象基類。 abc 庫定義抽象基類,以便其他類派生出新類。比如 collections 容器庫中就有此派生出的 collections.abc 類,派生出來的類可以進一步實現。
asyncio
非同步IO庫。 asyncio 庫是一個用 async/await 關鍵字編寫並發的庫,為多個非同步框架提供基礎功能,能夠實現高性能的網路、Web伺服器、資料庫連接和分布式任務隊列等。

淺層和深層復制操作。 庫提供對對象的拷貝,我們都知道要製作對象副本,是無法通過簡單值傳遞創建新變數的方式做到,因為新變數所指向的內存空間依舊是原對象本身,所以對新變數進行任何操作都會改變原對象。那麼, 庫就提供了製作對象副本的各種方法,會開辟一個新的內存空間存放副本對象,修改操作不會對原對象有任何干預。
csv
csv(Comma Separated Values)文件讀寫庫。此庫支持以純文本的形式存儲表格數據(數字和文本)。
operator
標准運算符替代函數庫。此庫是將 python 自有的運算符作為有效函數,比如表達式 x+y 可以用函數 operator.add(x, y) 表示;比如表達式 a*b 可以用函數 operator.mul(a, b) 表示,等等。
enum
枚舉庫。 enum 庫支持創建枚舉類來存儲大量同類型的不可變常量,以便其他函數調用。創建出來的枚舉類是可迭代對象,所以可以用 for-in 枚舉出所有常量。
heapq
堆隊列演算法。這個模塊提供了堆隊列演算法的實現,也稱為優先隊列演算法。優先隊列中的每個元素都有各自的優先順序,優先順序最高的元素最先得到服務。所以當我們要求前n最大/最小值的時候就可以用此演算法來實現, heapq 庫中也提供了相應函數實現。
http
HTTP 模塊。 http 模塊是一個包,收集了多個處理超文本傳輸協議的模塊:
urllib.request http 模塊通過 http.HTTPStatus 枚舉定義了HTTP狀態碼 以及相關聯消息。
profile、pstats
性能分析工具。 profile 模塊提供了 profile 和 cProfile 兩種不同實現的性能分析工具,可用來描述程序各個部分的執行時間和頻率,統計後的信息可以通過 pstats 模塊保存並使用。
ssl
TLS/SSL(傳輸安全協議)。此模塊提供對安全協議的支持,通過應用上下文,可將 TLS(傳輸層安全性協議)或其前身 SSL(安全套接層)支持安全協議,能為互聯網通信提供安全和數據完整性保障。一般 HTTPS 協議都支持 TLS/SSL 加密。
unitest
單元測試框架。 unitest 庫常用於單元測試,受到 JUnit 和其他主流測試庫的啟發, unitest 庫的功能和函數與它們有著相似的風格。
uuid
UUID庫。 uuid 庫主要用途是生成隨機字元串,庫中有多個版本的 UUID 對象方法,比如版本 1、3、4 和 5 的 uuid1() 、 uuid3() 、 uuid4() 和 uuid5() 。需要注意的是,如果要生成隨機字元串,可以使用 uuid1() 和 uuid4() ,但是 uuid1() 會存在隱私風險,因為生成的原理里邊包含用戶訪問計算機的網路地址,而 uuid4() 是通過隨機字元生成。
希望可以幫助到你。

⑥ python基礎教程 10-11例子如何執行

2020年最新Python零基礎教程(高清視頻)網路網盤

鏈接:

提取碼: 5kid 復制這段內容後打開網路網盤手機App,操作更方便哦

若資源有問題歡迎追問~


⑦ python 如何畫出KD數

簡單的KNN演算法在為每個數據點預測類別時都需要遍歷整個訓練數據集來求解距離,這樣的做法在訓練數據集特別大的時候並不高效,一種改進的方法就是使用kd樹來存儲訓練數據集,這樣可以使KNN分類器更高效。
KD樹的主要思想跟二叉樹類似,我們先來回憶一下二叉樹的結構,二叉樹中每個節點可以看成是一個數,當前節點總是比左子樹中每個節點大,比右子樹中每個節點小。而KD樹中每個節點是一個向量(也可能是多個向量),和二叉樹總是按照數的大小劃分不同的是,KD樹每層需要選定向量中的某一維,然後根據這一維按左小右大的方式劃分數據。在構建KD樹時,關鍵需要解決2個問題:(1)選擇向量的哪一維進行劃分(2)如何劃分數據。第一個問題簡單的解決方法可以是選擇隨機選擇某一維或按順序選擇,但是更好的方法應該是在數據比較分散的那一維進行劃分(分散的程度可以根據方差來衡量)。好的劃分方法可以使構建的樹比較平衡,可以每次選擇中位數來進行劃分,這樣問題2也得到了解決。下面是建立KD樹的Python代碼:
def build_tree(data, dim, depth):
"""
建立KD樹

Parameters
----------
data:numpy.array
需要建樹的數據集
dim:int
數據集特徵的維數
depth:int
當前樹的深度
Returns
-------
tree_node:tree_node namedtuple
樹的跟節點
"""
size = data.shape[0]
if size == 0:
return None
# 確定本層劃分參照的特徵
split_dim = depth % dim
mid = size / 2
# 按照參照的特徵劃分數據集
r_indx = np.argpartition(data[:, split_dim], mid)
data = data[r_indx, :]
left = data[0: mid]
right = data[mid + 1: size]
mid_data = data[mid]
# 分別遞歸建立左右子樹
left = build_tree(left, dim, depth + 1)
right = build_tree(right, dim, depth + 1)
# 返回樹的根節點
return Tree_Node(left=left,
right=right,
data=mid_data,
split_dim=split_dim)


對於一個新來的數據點x,我們需要查找KD樹中距離它最近的節點。KD樹的查找演算法還是和二叉樹查找的演算法類似,但是因為KD樹每次是按照某一特定的維來劃分,所以當從跟節點沿著邊查找到葉節點時候並不能保證當前的葉節點就離x最近,我們還需要回溯並在每個父節點上判斷另一個未查找的子樹是否有可能存在離x更近的點(如何確定的方法我們可以思考二維的時候,以x為原點,當前最小的距離為半徑畫園,看是否與劃分的直線相交,相交則另一個子樹中可能存在更近的點),如果存在就進入子樹查找。
當我們需要查找K個距離x最近的節點時,我們只需要維護一個長度為K的優先隊列保持當前距離x最近的K個點。在回溯時,每次都使用第K短距離來判斷另一個子節點中是否存在更近的節點即可。下面是具體實現的python代碼:
def search_n(cur_node, data, queue, k):
"""
查找K近鄰,最後queue中的k各值就是k近鄰

Parameters
----------
cur_node:tree_node namedtuple
當前樹的跟節點
data:numpy.array
數據
queue:Queue.PriorityQueue
記錄當前k個近鄰,距離大的先輸出
k:int
查找的近鄰個數
"""
# 當前節點為空,直接返回上層節點
if cur_node is None:
return None
if type(data) is not np.array:
data = np.asarray(data)
cur_data = cur_node.data
# 得到左右子節點
left = cur_node.left
right = cur_node.right
# 計算當前節點與數據點的距離
distance = np.sum((data - cur_data) ** 2) ** .5
cur_split_dim = cur_node.split_dim
flag = False # 標記在回溯時是否需要進入另一個子樹查找
# 根據參照的特徵來判斷是先進入左子樹還是右子樹
if data[cur_split_dim] > cur_data[cur_split_dim]:
tmp = right
right = left
left = tmp
# 進入子樹查找
search_n(left, data, queue, k)
# 下面是回溯過程
# 當隊列中沒有k個近鄰時,直接將當前節點入隊,並進入另一個子樹開始查找
if len(queue) < k:

neg_distance = -1 * distance
heapq.heappush(queue, (neg_distance, cur_node))
flag = True
else:
# 得到當前距離數據點第K遠的節點
top_neg_distance, top_node = heapq.heappop(queue)
# 如果當前節點與數據點的距離更小,則更新隊列(當前節點入隊,原第k遠的節點出隊)
if - 1 * top_neg_distance > distance:
top_neg_distance, top_node = -1 * distance, cur_node
heapq.heappush(queue, (top_neg_distance, top_node))
# 判斷另一個子樹內是否可能存在跟數據點的距離比當前第K遠的距離更小的節點
top_neg_distance, top_node = heapq.heappop(queue)
if abs(data[cur_split_dim] - cur_data[cur_split_dim]) < -1 * top_neg_distance:
flag = True
heapq.heappush(queue, (top_neg_distance, top_node))
# 進入另一個子樹搜索
if flag:
search_n(right, data, queue, k)525354555657

以上就是KD樹的Python實踐的全部內容,由於本人剛接觸python不久,可能實現上並不優雅,也可能在演算法理解上存在偏差,如果有任何的錯誤或不足,希望各位賜教。

熱點內容
java的job 發布:2025-02-12 23:38:43 瀏覽:892
我的世界伺服器授權指令 發布:2025-02-12 23:30:13 瀏覽:596
電腦伺服器號在哪裡找 發布:2025-02-12 23:22:29 瀏覽:12
linux查看系統是32位 發布:2025-02-12 23:17:29 瀏覽:989
從資料庫中隨機取資料庫數據 發布:2025-02-12 23:17:25 瀏覽:878
ftp下載軟體安卓 發布:2025-02-12 23:07:24 瀏覽:567
c搜索演算法 發布:2025-02-12 23:05:47 瀏覽:862
返回伺服器地址 發布:2025-02-12 23:05:45 瀏覽:181
我的世界推薦在線伺服器 發布:2025-02-12 23:00:18 瀏覽:462
什麼是解壓目錄 發布:2025-02-12 22:49:24 瀏覽:981