一、利用python列表實現堆棧和隊列
堆棧:
堆棧是一個后進先出的數據結構,其工作方式就像生活中常見到的直梯,先進去的人肯定是最后出。
我們可以設置一個類,用列表來存放棧中的元素的信息,利用列表的append()和pop()方法可以實現棧的出棧pop和入棧push的操作,list.append(obj)意思是向列表添加一個對象obj,list.pop(index=-1)意思是刪除指定位置的對象,默認是最后一個對象,也就是說list.pop(),是刪除列表中下標最大的元素。

# 后進先出 class Stack(): def __init__(self,size): self.size=size self.stack=[] self.top=-1 def push(self,x): # 入棧之前檢查棧是否已滿 if self.isfull(): raise exception("stack is full") else: self.stack.append(x) self.top=self.top+1 def pop(self): # 出棧之前檢查棧是否為空 if self.isempty(): raise exception("stack is empty") else: self.top=self.top-1 self.stack.pop() def isfull(self): return self.top+1 == self.size def isempty(self): return self.top == '-1' def showStack(self): print(self.stack) s=Stack(10) for i in range(6): s.push(i) s.showStack() for i in range(3): s.pop() s.showStack() """ 類中有top屬性,用來指示棧的存儲情況,初始值為1,一旦插入一個元素,其值加1,利用top的值樂意判定棧是空還是滿。 執行時先將0,1,2,3,4,5依次入棧,然后刪除棧頂的前三個元素 """
基本FIFO隊列
class Queue.Queue(maxsize=0)
FIFO即First in First Out,先進先出。Queue提供了一個基本的FIFO容器,使用方法很簡單,maxsize是個整數,指明了隊列中能存放的數據個數的上限。一旦達到上限,插入會導致阻塞,直到隊列中的數據被消費掉。如果maxsize小於或者等於0,隊列大小沒有限制。
舉個栗子:
import Queue q = Queue.Queue() # 建一個隊列 先進先出 for i in range(5): # 放五個元素進去 q.put(i) while not q.empty(): # 當隊列不為空時,循環取值 print q.get()
輸出:
0
1
2
3
4
LIFO隊列
class Queue.LifoQueue(maxsize=0)
LIFO即Last in First Out,后進先出。與棧的類似,使用也很簡單,maxsize用法同上
再舉個栗子:
import Queue q = Queue.LifoQueue() # 建一個后進先出的隊列 for i in range(5): # 放五個值進去 q.put(i) while not q.empty(): # 循環全部取出所有值 print q.get()
輸出 :
4
3
2
1
0
優先級隊列
class Queue.PriorityQueue(maxsize=0)
構造一個優先隊列。maxsize用法同上。
隊列:
隊列是一種先進先出的數據類型,它的跟蹤原理類似於在超市收銀處排隊,隊列里的的第一個人首先接受服務, 新的元素通過入隊的方式添加到隊列的末尾,而出隊就是將隊列的頭元素刪除。 我們可以設置一個類,用列表來存放棧中元素的信息,利用列表的append()和pop()方法可以實現隊列的入隊enqueue和出隊dequeue的操作, 上面棧一個元素每次出去是列表的最后一個,直接用list.pop()出棧,而出隊列每次是第一個,所以要用list.pop(0)出隊列

# 先進先出 class Queue(): def __init__(self,size): self.size=size self.front=-1 self.rear=-1 self.queue=[] def enqueue(self,ele): # 入隊操作 if self.isfull(): raise exception("queue is full") else: self.queue.append(ele) self.rear=self.rear+1 def dequeue(self): # 出隊操作 if self.isempty(): raise exception("queue is empty") else: self.queue.pop(0) self.front=self.front+1 def isfull(self): return self.rear-self.front+1 == self.size def isempty(self): return self.front == self.rear def showQueue(self): print(self.queue) q=Queue(10) for i in range(6): q.enqueue(i) q.showQueue() for i in range(3): q.dequeue() q.showQueue() print(q.isempty()) """ 類中設置兩個屬性分別為front和rear來模擬隊列的頭尾指針,通過它們值的關系可以判定隊列是空還是滿 """
一些常用方法
task_done()
意味着之前入隊的一個任務已經完成。由隊列的消費者線程調用。每一個get()調用得到一個任務,接下來的task_done()調用告訴隊列該任務已經處理完畢。
如果當前一個join()正在阻塞,它將在隊列中的所有任務都處理完時恢復執行(即每一個由put()調用入隊的任務都有一個對應的task_done()調用)。
join()
阻塞調用線程,直到隊列中的所有任務被處理掉。
只要有數據被加入隊列,未完成的任務數就會增加。當消費者線程調用task_done()(意味着有消費者取得任務並完成任務),未完成的任務數就會減少。當未完成的任務數降到0,join()解除阻塞。
put(item[, block[, timeout]])
將item放入隊列中。
- 如果可選的參數block為True且timeout為空對象(默認的情況,阻塞調用,無超時)。
- 如果timeout是個正整數,阻塞調用進程最多timeout秒,如果一直無空空間可用,拋出Full異常(帶超時的阻塞調用)。
- 如果block為False,如果有空閑空間可用將數據放入隊列,否則立即拋出Full異常
其非阻塞版本為put_nowait
等同於put(item, False)
get([block[, timeout]])
從隊列中移除並返回一個數據。block跟timeout參數同put
方法
其非阻塞方法為`get_nowait()`相當與get(False)
empty()
如果隊列為空,返回True,反之返回False