2012-01-06 58 views
7

我明白Stack()Stack<T>是如何工作的,但我真的不能看到任何情況下,數組,List<T>IEnumerable<T>不是一個更好和更容易的選擇。什麼時候在C#中使用堆棧<T>集合?

任何人都可以提供我使用的Stack<T>的現實世界的例子?

+3

準確地說,當你想要強制你的集合像棧一樣被操縱時,哪個List不能保證。 IEnumerable是完全不同的東西。 – 2012-01-06 22:41:12

+0

好的。你能提供一個我想要堆棧行爲的例子嗎? – jhovgaard 2012-01-06 22:44:01

+0

hmm'Stack '的功能看起來好像是'List '的一個子集,所以我同意它看起來不是最有用的集合。只有公開暴露時才需要強制執行堆棧行爲。但是在這種情況下,在內部集合中公開某種封裝通常是一個更好的主意,所以對於這種封裝並不是非常有用。所以我肯定會看到'IStack '接口的用法,但對於普通的集合類'Stack '來說並不是那麼多。 – CodesInChaos 2012-01-06 22:48:49

回答

9

理想的情況下使用,或根據需要創建,反映事物在現實世界中是如何工作的,你在代碼建模的事情類。這樣的類給我們提供了一個抽象層次,所以我們可以根據我們的建模/模擬進行編碼。另外,當編碼一些複雜的東西時,使用熟悉的範例會有所幫助。就是說:哦,這個Fuzzinator類使用堆棧。我知道堆棧是什麼以及它是如何工作的。其次,更高級別的抽象類爲我們提供了可用的代碼(我們假設.NET框架已經過測試),併爲我們節省了重新發明車輪的時間和痛苦。

第三,代碼更易於閱讀,更易於理解,更易於更改等等。它更易於維護。

使用具有更多細化功能的類有助於限制我們如何使用它。

在整個應用程序僅僅是更好當它在抽象的適當水平的真實編碼。

堆棧就是其中的一個類。

我的HP-41X計算器使用堆棧進行算術運算。這種計算方法被稱爲RPN - 逆波蘭表示法。

如果我模擬一個自助餐廳,堆棧將是完美的堆棧板。板從頂部上下堆疊。不是中間的,而是最後的;只是頂部。堆棧。我只能使用Push()和Pop()板來使代碼更加簡單明瞭。

或者,想象用C#等價的子原子粒子編碼 - 泛型集合或通用IEnumerable等等。我最終使用了通用實用程序方法和通用名稱以及帶有多變量參數的通用名稱我正在堆疊盤子的事實。

+0

你剛剛給了我一個「哦,現在我明白了!」 - 經驗。謝謝! :-) – jhovgaard 2012-01-06 23:23:53

1

繼承人的一種方式我用堆棧:

我有這樣一個頁面嚮導,有需要以特定的順序進行dispalyed和處理5個用戶控件,用戶應該能夠在任何時候按順序返回到最後一頁。

我使用一個基於堆棧的狀態機來跟蹤用戶通過嚮導進步。

每次它們向前移動時,我都會將狀態機的狀態推入會話存儲堆棧,並且如果它們請求返回,則彈出最高值並將計算機設置爲新的堆棧頂層值。 (反過來,顯示器以及負荷適當控制)

還有一個:

我不得不建立一些非常定製的服務器應用程序的安裝應用程序。我最終做的是將安裝的每一步都打破成其自己的通用組件,即複製文件的組件,編寫註冊表值的組件等。每個組件必須具有以下方法:執行安裝操作,撤銷安裝操作。

安裝的每一步,組件都被壓入堆棧。

現在,在任何時候,我有一個錯誤,我們只是彈出每個組件從堆棧,並運行撤消操作使我們細粒度安裝交易。

Stack's是你的朋友!

0

我會說,如果你是在概念上構建一個堆棧的東西。假設你正在塑造一個小而深的抽屜,並將書放在抽屜裏。這將遵循「先進後出」的範式,這是一般堆棧的要點。

您沒有的書籍列表或某種枚舉的 - 你對他們有特定的順序...即,它們被添加的順序相反。

3

Depth first tree traversal。與隊列相反,廣度優先樹遍歷。


當用戶在他們周圍導航時管理呈現不同的屏幕。顯示一個屏幕將其推入堆棧,然後「回退」彈出它。繪製頂部屏幕。


當你想要一個集合,您可以添加的東西,當你得到的東西是最近添加的總是知道。


實現撤銷/重做功能。

+0

此外,我相信這是什麼*插入這裏的人口增加*加入一條線時使用。 – 2012-01-06 22:54:07

2

可以重寫遞歸方法如迭代同行通過控制開啓和關閉堆棧當地人容易得多。查看Jon Skeet的排序使用堆棧here

+1

+1用於討論一般情況。我會補充一點,如果你有一個深度遞歸算法,這種方法會很有幫助,因爲它可以讓你深度遞歸而不會溢出調用堆棧:當然,堆棧實例存儲在堆中。 – phoog 2012-01-06 23:23:33

1

堆棧和隊列在內部使用一個數組。如果你用聰明的方式使用數組,你很可能已經將它們用在了堆棧或隊列中,就像時尚一樣。通常你需要在棧和隊列之間做出決定。 需要堆棧的典型示例是depth first search。如果將集合更改爲隊列,則您已實施了廣度優先搜索。

另一個示例是在你通過堆棧通過一個生產者和消費者之間數據如果處理順序是不相關的重多線程。其基本原理是,如果要處理大量數據,CPU最好使用最新添加的數據塊在另一個線程上進行進一步處理,以獲得更好的緩存局部性。

而且不勝枚舉....

+0

我的印象是堆棧和隊列通常使用鏈接列表來實現。 – SundayMonday 2012-01-06 23:25:00

+1

至少.NET BCL在內部使用數組實現隊列和堆棧。由於增加的內存消耗和更復雜的對象圖,鏈接列表在.NET中表現不佳,這將使得GC更加昂貴。通常你的意思是C++或...?由於Stack和Queue通常不用於添加或刪除中間鏈接列表中的元素,因此在這裏沒有多大意義。 – 2012-01-09 08:48:15

1

棧在文本解析算法中經常使用,例如「4 + 5 + 6」的評價。有關使用堆棧解析文本的應用程序的實際示例,請參閱HTMLAgilityPack。該組件是用來解析HTML,它包括源代碼,所以你可以看到如何以及在何處使用堆棧...

0

Stack<T>的功能真的好像的List<T>一個子集(少數改名的方法) ,所以我同意它看起來不像是最有用的收藏本身。當在算法中內部使用時,即使可能稍微不習慣,List<T>也可以輕鬆替換它。

強制執行堆棧行爲如果公開曝光纔是必需的。但是在這種情況下,通過內部集合公開某種封裝通常是一個更好的主意,因此它對於這種封裝看起來並不是非常有用。我當然會看到用於接口的接口,但不是那麼多純收集類Stack<T>

我的結論是,我也不會包含在框架Stack<T>類,只是一個IStack<T>接口。 BCL收藏通常看起來不是很好。

,另一方面ConcurrentStack<T>似乎更加有用。

+2

如果你打算爲'IStack '定義一個接口,你會不會至少包含一個實現它的類? (即'Stack '類)。 – 2012-01-06 22:59:03

+0

@George我覺得這個類寧願成爲另一個類似於'ReadOnlyCollection '的集合的包裝。或者甚至可能是'List '上的明確的接口實現,或者兩者兼而有之。 – CodesInChaos 2012-01-06 23:11:22

+1

'Stack '是否是一個包裝器只是一個實現細節。我肯定會說讓List 來實現它會導致一個糟糕的類,我不會真的想在列表中使用Push和Pop方法。我寧願有一個名單列表'和堆棧的'堆棧'。 – 2012-01-06 23:43:58

1

將表達式從中綴表示法轉換爲前綴表示法時,堆棧很有用。例如:瀏覽器歷史記錄的

a + b(+ a b)

-1

飼養的軌道是堆棧中使用。同樣,對於編輯等的「撤銷」。 類似地,一些倉庫控制系統使用堆棧和隊列來管理需要爲貨物選擇物品的順序。

相關問題