Python 中的棧

在本教程中,我們將學習棧的基礎知識,並使用 Python 代碼實現它。

什麼是棧?

棧是一種線性數據結構,其中數據被一個對象排列在另一個對象之上。它以後進先出的方式存儲數據。數據以類似的順序存儲,因為盤子在廚房裡一個接一個地排列。棧的簡單示例是編輯器中的撤銷功能。撤消功能適用於我們已經完成的最後一個事件。

我們總是從一堆盤子中挑選最後一個。在棧中,新元素插入在一端,元素只能從該端移除。

我們可以在棧中執行兩個操作- PUSH 和 POP 。推送操作是當我們添加一個元素時,而彈出操作是當我們從棧中移除一個元素時。

棧方法

Python 提供了以下常用於棧的方法。

  • 空()- 如果棧為空,則返回真。時間複雜度為 O(1)。
  • size() – 返回棧的長度。時間複雜度為 O(1)。
  • top() – 這個方法返回棧最後一個元素的地址。時間複雜度為 O(1)。
  • push(g)—該方法在棧尾加入元素『g』—時間複雜度為 O(1)。
  • pop() – 此方法移除棧的最頂層元素。時間複雜度為 O(1)。

棧的實現

Python 提供了各種方法來實現棧。在本節中,我們將討論使用 Python 及其模塊實現棧。

我們可以通過以下方式在 Python 中實現棧。

  • 目錄
  • 出列
  • LifeQueue

使用列表實現

Python 列表可以用作棧。它使用 append() 方法將元素插入列表,其中棧使用 push() 方法。該列表還提供了 pop()方法來移除最後一個元素,但是該列表存在一些缺點。列表隨著增長而變得緩慢。

列表將新元素存儲在下一個元素中。如果列表變大,超出了一個內存塊,Python 就會分配一些內存。這就是列表變得緩慢的原因。讓我們理解下面的例子-


# initial empty stack
my_stack = []

# append() function to push 
# element in the my_stack 
my_stack.append('x')
my_stack.append('y')
my_stack.append('z')

print(my_stack)

# pop() function to pop 
# element from my_stack in  
# LIFO order 
print('\nElements poped from my_stack:')
print(my_stack.pop())
print(my_stack.pop())
print(my_stack.pop())

print('\nmy_stack after elements are poped:')
print(my_stack) 

輸出:

['x', 'y', 'z']

Elements poped from my_stack:
z
y
x  

my_stack after elements are poped:
[]
Traceback (most recent call last):
  File "C:/Users/DEVANSH SHARMA/PycharmProjects/Hello/Stack.py", line 21, in <module>
    print(my_stack.pop())
IndexError: pop from empty list

解釋-

在上面的代碼中,我們定義了一個空列表。我們使用 append() 方法逐個插入元素。那類似於推()的方法。我們還使用 pop() 方法移除了元素。 pop() 方法返回列表的最後一個元素。

使用 collection.deque 實現

collections模塊提供了 deque 類,用於創建 Python 棧。德格發音為「甲板」,意思是「雙頭隊列」。deque 比列表更受歡迎,因為它比列表執行追加和彈出操作更快。時間複雜度為 O(1),其中列表取 O(n)。

讓我們理解下面的例子-


from collections import deque

my_stack = deque()

# append() function is used to push 
# element in the my_stack 
my_stack.append('a')
my_stack.append('b')
my_stack.append('c')

print('Initial my_stack:')
print(my_stack)

# pop() function is used to pop 
# element from my_stack in  
# LIFO order 
print('\nElements poped from my_stack:')
print(my_stack.pop())
print(my_stack.pop())
print(my_stack.pop())

print('\nmy_stack after elements are poped:')
print(my_stack) 

輸出:

Initial my_stack:
deque(['a', 'b', 'c'])
Elements poped from my_stack:
c
b
a
my_stack after elements are poped:
deque([])

說明:

上面的代碼幾乎與前面的例子相似。但是,唯一不同的是,我們已經從collections模塊中導入了 deque。

雙隊列與列表

該列表將元素緊挨著存儲,並使用連續的內存。這對於幾個操作來說是最有效的,比如索引列表。例如-獲取列表 1【2】很快,因為 Python 知道特定元素的確切位置。連續內存還允許切片在列表中很好地工作。

列表比其他對象消耗更多的時間來追加一些對象。如果連續內存塊已滿,它將獲得另一個比正常的 append() 函數花費更長時間的塊。

使用queue模塊實現

queue模塊有後進先出隊列,與棧相同。通常,隊列使用put()方法添加數據,使用方法獲取數據。

下面是隊列中可用的幾種方法。

  • 空()- 如果隊列為空,返回真;否則返回 false。
  • maxsize() – 此方法用於設置隊列中允許的最大元素數量。
  • get() – 它返回並從隊列中移除元素。有時間。隊列可以為空;它一直等到元素可用。
  • 已滿()- 如果隊列已滿,則返回真。默認情況下,隊列被定義為 maxsize = 0。在這種情況下,它不會返回真。
  • put(item) – 它將元素添加到隊列中;如果隊列已滿,請等待直到空間可用。
  • put_nowait(item) – 它不延遲地將元素添加到隊列中。
  • qsize() – 返回隊列的大小。

讓我們理解queue模塊的以下示例。

示例-


# Implementing stack using the queue module
from queue import LifoQueue 

# Initializing a my_stack stack with maxsize
my_stack = LifoQueue(maxsize = 5)

# qsize() display the number of elements
# in the my_stack 
print(my_stack.qsize()) 

# put() function is used to push
# element in the my_stack 
my_stack.put('x')
my_stack.put('y')
my_stack.put('z')

print("Stack is Full: ", my_stack.full()) 
print("Size of Stack: ", my_stack.qsize()) 

# To pop the element we used get() function
# from my_stack in 
# LIFO order 
print('\nElements poped from the my_stack') 
print(my_stack.get()) 
print(my_stack.get()) 
print(my_stack.get()) 

print("\nStack is Empty: ", my_stack.empty())

輸出:

0
Stack is Full:  False
Size of Stack:  3

Elements poped from the my_stack
z
y
x

Stack is Empty:  True

解釋-

在上圖中,我們已經導入了queue模塊,這是一個 LIFOqueue 。它的工作原理與棧相同,但是這個模塊包括一些上面提到的附加功能。我們用 maxsize 定義了一個棧,這意味著它最多可以容納五個值。

初始數組大小為零;我們使用 put()方法將三個元素推入棧。現在,我們再次檢查棧是否為空以及棧的大小。棧中有三個元素。我們使用 get()方法彈出了元素。它首先移除最後添加的元素。移除整個元素後,我們得到一個空棧。

Python 棧和線程

我們也可以在多線程程序中使用 Python 棧。這是一個高級主題,但不經常使用,因此如果您對線程不感興趣,可以跳過這一部分。

如果我們在程序中使用線程,列表和 deque 的行為會有所不同。在多線程編程中使用列表是危險的,因為它不是線程安全的。

另一方面,deque 有點複雜,因為它的 append() 和 pop() 方法是原子的,這意味著它們不會被其他線程中斷。

我們可以使用 deque 來構建多線程程序,但是它在未來可能不會帶來太多的複雜性。

現在問題來了,如何用線程構建 Python 棧的程序。

答案是我們可以使用後進先出隊列,我們知道後進先出代表什麼。它使用 put() 和get()來添加和移除棧元素。

棧的哪個實現應該考慮?

我們已經提到了三種在 Python 中實現棧的方法。以上方法各有利弊。

讓我們消除困惑;我們使用的是帶線程的棧,你應該使用 Lifoqueue ,但是要確保它的彈出和推送元素的性能。但是如果你不使用穿線,請使用德克爾。

我們也可以使用列表來實現棧,但是列表可能會有潛在的內存重新分配問題。列表和 de quee 在界面中是相同的,但是 de quee 沒有內存分配問題。

結論

我們已經簡單定義了棧及其實現。Python 棧可以用於現實生活中的程序。我們可以根據自己的需求選擇實現方法。我們還定義了帶有線程環境的 Python 棧。


原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/237522.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 12:05
下一篇 2024-12-12 12:05

相關推薦

  • Python列表中負數的個數

    Python列表是一個有序的集合,可以存儲多個不同類型的元素。而負數是指小於0的整數。在Python列表中,我們想要找到負數的個數,可以通過以下幾個方面進行實現。 一、使用循環遍歷…

    編程 2025-04-29
  • Python中引入上一級目錄中函數

    Python中經常需要調用其他文件夾中的模塊或函數,其中一個常見的操作是引入上一級目錄中的函數。在此,我們將從多個角度詳細解釋如何在Python中引入上一級目錄的函數。 一、加入環…

    編程 2025-04-29
  • Python計算陽曆日期對應周幾

    本文介紹如何通過Python計算任意陽曆日期對應周幾。 一、獲取日期 獲取日期可以通過Python內置的模塊datetime實現,示例代碼如下: from datetime imp…

    編程 2025-04-29
  • Python周杰倫代碼用法介紹

    本文將從多個方面對Python周杰倫代碼進行詳細的闡述。 一、代碼介紹 from urllib.request import urlopen from bs4 import Bea…

    編程 2025-04-29
  • 如何查看Anaconda中Python路徑

    對Anaconda中Python路徑即conda環境的查看進行詳細的闡述。 一、使用命令行查看 1、在Windows系統中,可以使用命令提示符(cmd)或者Anaconda Pro…

    編程 2025-04-29
  • Python程序需要編譯才能執行

    Python 被廣泛應用於數據分析、人工智慧、科學計算等領域,它的靈活性和簡單易學的性質使得越來越多的人喜歡使用 Python 進行編程。然而,在 Python 中程序執行的方式不…

    編程 2025-04-29
  • python強行終止程序快捷鍵

    本文將從多個方面對python強行終止程序快捷鍵進行詳細闡述,並提供相應代碼示例。 一、Ctrl+C快捷鍵 Ctrl+C快捷鍵是在終端中經常用來強行終止運行的程序。當你在終端中運行…

    編程 2025-04-29
  • Python字典去重複工具

    使用Python語言編寫字典去重複工具,可幫助用戶快速去重複。 一、字典去重複工具的需求 在使用Python編寫程序時,我們經常需要處理數據文件,其中包含了大量的重複數據。為了方便…

    編程 2025-04-29
  • Python清華鏡像下載

    Python清華鏡像是一個高質量的Python開發資源鏡像站,提供了Python及其相關的開發工具、框架和文檔的下載服務。本文將從以下幾個方面對Python清華鏡像下載進行詳細的闡…

    編程 2025-04-29
  • Python編程二級證書考試相關現已可以上網購買

    計算機二級Python考試是一項重要的國家級認證考試,也是Python編程的入門考試。與其他考試一樣,Python編程二級證書的考生需要進入正式考試,而為了備考,這篇文章將詳細介紹…

    編程 2025-04-29

發表回復

登錄後才能評論