Python数据结构学习笔记——队列和双端队列
目錄
- 一、隊列的定義
- 二、隊列 實現步驟分析
- 三、隊列的Python實現代碼
- 四、隊列的應用
- 六人傳土豆游戲
- 五、雙端隊列的定義
- 六、雙端隊列 實現步驟分析
- 七、雙端隊列的Python實現代碼
- 八、雙端隊列的應用
- 回文檢測器
- 結語
一、隊列的定義
隊列和棧一樣,也是元素的有序集合,其元素的順序取決于添加順序或移除順序,它也有兩端,稱作頭部和尾部,棧中元素的添加操作和移除操作與棧不一樣,添加操作發生在隊列的尾部,移除操作發生在隊列的頭部。
隊列中最先添加的元素將最先被移除,隊列的排序原則被稱作FIFO,即先進先出,最先添加的元素在隊列頭部,它最先最移出隊列。
這種排列方式可以比喻成日常生活中的排隊,很多人排成一隊,所有的人從隊的一端入隊,從另一端出隊,其中不能插隊,后到的人若想進入隊列,只能從隊尾進入隊列。
隊列的相關應用例子:
在操作系統使用一些隊列來控制計算機進程。
調度機制往往基于一個隊列算法,其目標是盡可能快地執行程序,同時服務盡可能多的用戶。在打字時,我們有時會發現字符出現的速度比擊鍵速度慢。這是由于計算機正在做其他的工作。擊鍵操作被放入一個類似于隊列的緩沖區,以便對應的字符按正確的順序顯示。
二、隊列 實現步驟分析
與棧一樣,通過Python中的類與對象,在類中定義幾個方法,使用列表來實現隊列的相關操作,這里是將列表的末尾作為隊列的頭部,隊列的尾部是列表下標為0處的位置,隊列的操作有:
1、創建一個空隊列,通過構造方法創建一個空列表;
2、向隊列(尾部)中添加元素,通過列表中的insert()實現添加新元素至隊列中,由于是向隊列尾部添加元素,添加列表中的第一個元素,即下標為0的元素;
def add(self, item):self.items.insert(0, item) # 在隊列的尾部添加元素,它需要一個元素作為參數3、刪除隊列頭部元素,通過列表中的pop()實現刪除隊列頭部元素,由于未指定參數,所以該方法刪除列表中的末尾元素,即刪除的是隊列頭部元素;
def delete(self):return self.items.pop() # 刪除隊列頭部的元素,不需要參數,它會返回一個元素,并修改隊列的內容4、返回隊列的頭部元素,通過len()取得隊列(列表)的長度,由于列表的下標是從0開始,所以要減1,即可索引返回第一位元素;
def display(self):return self.items[len(self.items) - 1] # 返回隊列的頭部元素5、檢查隊列是否為空,通過比較運算符“==”比較隊列是否為空,若為空,則返回布爾值False,若不為空,則返回True;
def isEmpty(self):return self.items == [] # 檢查隊列是否為空,不需要參數,且返回一個布爾值來表示6、返回隊列中元素數目,通過len()取所有元素的值,即返回隊列中元素的數目。
def size(self):return len(self.items) # 返回隊列中元素的數目,不需要參數,卻返回一個整數來表示三、隊列的Python實現代碼
完整代碼如下:
# 通過列表實現隊列的操作 class Queue:def __init__(self):self.items = [] # 創建一個空隊列,不需要參數,且會返回一個空隊列def add(self, item):self.items.insert(0, item) # 在隊列的尾部添加元素,它需要一個元素作為參數def delete(self):return self.items.pop() # 刪除隊列頭部的元素,不需要參數,它會返回一個元素,并修改隊列的內容def display(self):return self.items[len(self.items) - 1] # 返回隊列的頭部元素def isEmpty(self):return self.items == [] # 檢查隊列是否為空,不需要參數,且返回一個布爾值來表示def size(self):return len(self.items) # 返回隊列中元素的數目,不需要參數,卻返回一個整數來表示# 測試 q = Queue()# q是一個新創建的空隊列,創建一個對象,即對象名稱=類名稱() print(q.isEmpty()) # 查詢隊列是否為空 print(q.size()) # 返回隊列中元素的數目 q.add(False) # 在隊列的尾部添加一個元素 print(q.display())# 返回隊列的頭部元素 q.add("qwet") q.add(0) print(q.display()) print(q.size()) q.delete() # 刪除隊列頭部的元素 print(q.display()) print(q.size()) print(q.isEmpty())運行結果如下:
四、隊列的應用
六人傳土豆游戲
六個人傳土豆游戲可模擬為隊列的循環,通過隊列來模擬一個環,即隊列頭部的出隊移至尾部,然后入隊進入隊列的尾部從而一直循環傳下去。在出隊和入隊N次之后,此時位于隊列頭部的人出局,新一輪的游戲開始,如此反復像一個圓環一樣依次循環下去,直到隊列中只剩下一個名字,即最后隊伍的元素數目為1。
定義一個Pass()函數,傳遞土豆的常量為7,首先通過一個for循環遍歷參加傳遞土豆游戲的所有人使其都添加到隊列中,通過add(name_people)方法實現程序實現,name_people參數可傳入一個列表,然后通過while循環條件為隊列中的元素是否大于1,若大于1則while循環一直執行其內部代碼塊下去,在while循環內根據所輸入的傳遞土豆的常量通過for循環中的range()函數確定相應的循環次數,然后依次將所刪除的頭部元素再添加到隊列的尾部,若循環次數(傳遞土豆的常量)達到后,此時刪除隊列頭部的元素,該人出局;若直到隊伍的元素數目等于1時,結束while循環返回隊列中的只剩下的那個元素,完整代碼及解析如下:
運行結果如下:
我們可以對六人傳土豆游戲進行進一步的修改,比如允許隨機計數,從而使每一輪的結果都不可預測,從而使游戲更加公平,由于是隨機計數,可以使用random模塊來生成隨機整數,選定一個范圍使計算機自動生成。
改進后的六人傳土豆游戲程序代碼及解析如下:
運行結果如下,每次產生的計數常量值不同導致結果不同:
第一次運行:
第二次運行:
五、雙端隊列的定義
雙端隊列與隊列類似,它有前、后兩端,但無論是添加元素或刪除元素都可以在兩端實現,它的排序原則可以為棧的后進先出,也可以為隊列的先進先出,這取決于使用者,可以說雙端隊列是棧和隊列的結合。
六、雙端隊列 實現步驟分析
通過Python中的類與對象,在類中定義幾個方法,使用列表來實現雙端隊列的相關操作,這里是將列表的末尾作為雙端隊列的前端,雙端隊列的后端是列表下標索引為0的位置,雙端隊列的操作有:
1、創建一個空雙端隊列,通過構造方法創建一個空列表;
2、向雙端隊列兩端添加元素,分為向雙端隊列的前端或后端添加元素,前端通過append()方法向列表末尾添加元素,即向雙端隊列的前端添加;后端通過insert()方法在列表下標為0處列表的第一位元素,即雙端隊列的后端添加;
def addFront(self, item):self.items.append(item) # 在雙端隊列的前端添加元素,它需要一個元素作為參數def addRear(self, item):self.items.insert(0, item) # 在雙端隊列的后端添加元素,它需要一個元素作為參數3、刪除雙端隊列兩端元素,分為刪除雙端隊列的前端元素和刪除雙端隊列的后端元素,都通過使用pop()方法,前端不需要指定參數,使其刪除列表的末尾元素,即雙端隊列的前端元素;后端指定參數為0,使其刪除列表中下標為0的元素,即列表的第一位元素,從而刪除雙端的后端元素;
def deleteFront(self):return self.items.pop() # 刪除雙端隊列前端的元素,不需要參數,它會返回一個元素,并修改雙端隊列的內容def deleteRear(self):return self.items.pop(0) # 刪除雙端隊列后端的元素,不需要參數,它會返回一個元素,并修改雙端隊列的內容4、返回雙端隊列的兩端元素,通過len()先取得列表的長度,由于下標是從0開始,所以要減1,從而索引得到雙端隊列的前端元素;通過索引列表下標為0的元素得到雙端隊列的后端元素;
def displayFront(self):return self.items[len(self.items) - 1] # 返回雙端隊列的前端元素def displayRear(self):return self.items[0] # 返回雙端隊列的后端元素5、檢查雙端隊列是否為空,通過比較運算符“==”比較隊列是否為空,若為空,則返回布爾值False,若不為空,則返回True;
def isEmpty(self):return self.items == [] # 檢查雙端隊列是否為空,不需要參數,且返回一個布爾值來表示6、返回雙端隊列中元素數目,通過len()取所有元素的值,即返回隊列中元素的數目。
def size(self):return len(self.items) # 返回雙端隊列中元素的數目,不需要參數,卻返回一個整數來表示七、雙端隊列的Python實現代碼
完整代碼如下:
# 通過列表實現雙端隊列的操作 class Deque:def __init__(self):self.items = [] # 創建一個空雙端隊列,不需要參數,且會返回一個空雙端隊列def addFront(self, item):self.items.append(item) # 在雙端隊列的前端添加元素,它需要一個元素作為參數def addRear(self, item):self.items.insert(0, item) # 在雙端隊列的后端添加元素,它需要一個元素作為參數def deleteFront(self):return self.items.pop() # 刪除雙端隊列前端的元素,不需要參數,它會返回一個元素,并修改雙端隊列的內容def deleteRear(self):return self.items.pop(0) # 刪除雙端隊列后端的元素,不需要參數,它會返回一個元素,并修改雙端隊列的內容def displayFront(self):return self.items[len(self.items) - 1] # 返回雙端隊列的前端元素def displayRear(self):return self.items[0] # 返回雙端隊列的后端元素def isEmpty(self):return self.items == [] # 檢查雙端隊列是否為空,不需要參數,且返回一個布爾值來表示def size(self):return len(self.items) # 返回雙端隊列中元素的數目,不需要參數,卻返回一個整數來表示# 測試 d = Deque() # d是一個新創建的空雙端隊列,創建一個對象,即對象名稱=類名稱() print(d.isEmpty()) # 檢查雙端隊列是否為空 print(d.size()) # 返回雙端隊列中元素的數目 d.addFront(123456) # 向雙端隊列的前端添加元素 d.addFront("45@d") d.addRear("2021-1-14") # 向雙端隊列的后端添加元素 d.addRear("Z") print(d.size()) print(d.displayFront()) # 返回雙端隊列的前端元素 print(d.displayRear()) # 返回雙端隊列的后端元素 d.deleteFront() # 刪除雙端隊列的前端元素 print(d.size()) print(d.displayFront()) d.deleteRear() # 刪除雙端隊列的后端元素 print(d.size()) print(d.displayRear()) print(d.isEmpty())運行結果如下:
測試圖例:
八、雙端隊列的應用
回文檢測器
回文是指正著讀和反著讀都一樣的字符串,即成對稱的字符串,例如rar、toot、12321等等,我們可以通過一個雙端隊列來存儲字符串中的字符,通過從左往右的順序將字符串中的字符添加到雙端隊列的后端,然后通過定義一個條件,只有當雙端隊列的前端和后端相同時,才相互抵消刪除元素。一直這樣刪除下去,若輸入的字符串字符數為偶數,則最后將沒有字符;若輸入的字符串字符數為奇數,則最后只剩下一個字符,從而達到檢測回文的目的。
回文檢測器的完整代碼及解析如下:
運行結果如下:
結語
參考書籍:《Python數據結構與算法分析 第2版》
[美] 布拉德利·米勒(Bradley N. Miller) 戴維·拉努姆(DavidL. Ranum)|譯者:呂能 刁壽鈞
以上就是本次Python數據結構學習筆記棧的全部內容,篇幅較長,感謝您的閱讀和支持,若有表述或代碼中有不當之處,望指出!您的指出和建議能給博主帶來很大的動力!!!
總結
以上是生活随笔為你收集整理的Python数据结构学习笔记——队列和双端队列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python数据结构学习笔记——栈
- 下一篇: websocket python爬虫_p