1. 程式人生 > >詳細分析棧和佇列的資料結構的實現過程(Java 實現)

詳細分析棧和佇列的資料結構的實現過程(Java 實現)

[TOC] # 棧和佇列的資料結構的實現過程(Java 實現) ## 棧的資料結構的實現 ### 棧的基礎知識回顧 1. 棧是一種**線性結構**。 2. **相比陣列,棧對應的操作是陣列的子集。** - 也就是棧可基於陣列實現,可以將棧看成一種特殊的陣列。 3. **棧只能從一端新增元素,也只能從一端取出元素,這一端稱為棧頂**。 4. 棧是一種 **後進先出 (LIFO: Last In First Out)** 的資料結構。 ### 棧的常見應用 - 撤銷(Undo)操作 ![棧的應用_撤銷示例](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9teWJsb2dwaWN0dXJlLm9zcy1jbi1zaGVuemhlbi5hbGl5dW5jcy5jb20vJUU2JTk1JUIwJUU2JThEJUFFJUU3JUJCJTkzJUU2JTlFJTg0X0phdmFfJUU2JUEwJTg4JUU1JTkyJThDJUU5JTk4JTlGJUU1JTg4JTk3LyVFNiVBMCU4OCVFNyU5QSU4NCVFNSVCQSU5NCVFNyU5NCVBOF8lRTYlOTIlQTQlRTklOTQlODAlRTclQTQlQkElRTQlQkUlOEIuZ2lm) - 程式呼叫的系統棧 ![棧的應用_系統棧呼叫示例](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9teWJsb2dwaWN0dXJlLm9zcy1jbi1zaGVuemhlbi5hbGl5dW5jcy5jb20vJUU2JTk1JUIwJUU2JThEJUFFJUU3JUJCJTkzJUU2JTlFJTg0X0phdmFfJUU2JUEwJTg4JUU1JTkyJThDJUU5JTk4JTlGJUU1JTg4JTk3LyVFNiVBMCU4OCVFNyU5QSU4NCVFNSVCQSU5NCVFNyU5NCVBOF8lRTclQjMlQkIlRTclQkIlOUYlRTYlQTAlODglRTglQjAlODMlRTclOTQlQTglRTclQTQlQkElRTQlQkUlOEIuZ2lm) ![系統棧呼叫測試示例](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9teWJsb2dwaWN0dXJlLm9zcy1jbi1zaGVuemhlbi5hbGl5dW5jcy5jb20vJUU2JTk1JUIwJUU2JThEJUFFJUU3JUJCJTkzJUU2JTlFJTg0X0phdmFfJUU2JUEwJTg4JUU1JTkyJThDJUU5JTk4JTlGJUU1JTg4JTk3LyVFNyVCMyVCQiVFNyVCQiU5RiVFNiVBMCU4OCVFOCVCMCU4MyVFNyU5NCVBOCVFNiVCNSU4QiVFOCVBRiU5NSVFNyVBNCVCQSVFNCVCRSU4Qi5wbmc?x-oss-process=image/format,png) ### 基於陣列的棧的實現 對於棧這種資料結構,實現起來是十分簡單的,這裡實現以下幾個操作: 1. **入棧:void push(E element)** ![入棧示例](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9teWJsb2dwaWN0dXJlLm9zcy1jbi1zaGVuemhlbi5hbGl5dW5jcy5jb20vJUU2JTk1JUIwJUU2JThEJUFFJUU3JUJCJTkzJUU2JTlFJTg0X0phdmFfJUU2JUEwJTg4JUU1JTkyJThDJUU5JTk4JTlGJUU1JTg4JTk3LyVFNiVBMCU4OCVFNyU5QSU4NCVFNSVCQSU5NCVFNyU5NCVBOF8lRTUlODUlQTUlRTYlQTAlODglRTclQTQlQkElRTQlQkUlOEIuZ2lm) 2. **出棧: E pop()** ![出棧示例](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9teWJsb2dwaWN0dXJlLm9zcy1jbi1zaGVuemhlbi5hbGl5dW5jcy5jb20vJUU2JTk1JUIwJUU2JThEJUFFJUU3JUJCJTkzJUU2JTlFJTg0X0phdmFfJUU2JUEwJTg4JUU1JTkyJThDJUU5JTk4JTlGJUU1JTg4JTk3LyVFNiVBMCU4OCVFNyU5QSU4NCVFNSVCQSU5NCVFNyU5NCVBOF8lRTUlODclQkElRTYlQTAlODglRTclQTQlQkElRTQlQkUlOEIuZ2lm) 3. **檢視棧頂元素: E peek()** ![檢視棧頂元素示例](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9teWJsb2dwaWN0dXJlLm9zcy1jbi1zaGVuemhlbi5hbGl5dW5jcy5jb20vJUU2JTk1JUIwJUU2JThEJUFFJUU3JUJCJTkzJUU2JTlFJTg0X0phdmFfJUU2JUEwJTg4JUU1JTkyJThDJUU5JTk4JTlGJUU1JTg4JTk3LyVFNiVBMCU4OCVFNyU5QSU4NCVFNSVCQSU5NCVFNyU5NCVBOF8lRTYlOUYlQTUlRTclOUMlOEIlRTYlQTAlODglRTklQTElQjYlRTUlODUlODMlRTclQjQlQTAlRTclQTQlQkElRTQlQkUlOEIuZ2lm) 4. **獲取棧中元素個數: int getSize()** ![獲取棧中元素個數示例](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9teWJsb2dwaWN0dXJlLm9zcy1jbi1zaGVuemhlbi5hbGl5dW5jcy5jb20vJUU2JTk1JUIwJUU2JThEJUFFJUU3JUJCJTkzJUU2JTlFJTg0X0phdmFfJUU2JUEwJTg4JUU1JTkyJThDJUU5JTk4JTlGJUU1JTg4JTk3LyVFOCU4RSVCNyVFNSU4RiU5NiVFNiVBMCU4OCVFNCVCOCVBRCVFNSU4NSU4MyVFNyVCNCVBMCVFNCVCOCVBQSVFNiU5NSVCMCVFNyVBNCVCQSVFNCVCRSU4Qi5wbmc?x-oss-process=image/format,png) 5. **判斷棧是否為空: boolean: isEmpty()** ![判斷棧是否為空示例](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9teWJsb2dwaWN0dXJlLm9zcy1jbi1zaGVuemhlbi5hbGl5dW5jcy5jb20vJUU2JTk1JUIwJUU2JThEJUFFJUU3JUJCJTkzJUU2JTlFJTg0X0phdmFfJUU2JUEwJTg4JUU1JTkyJThDJUU5JTk4JTlGJUU1JTg4JTk3LyVFNSU4OCVBNCVFNiU5NiVBRCVFNiVBMCU4OCVFNiU5OCVBRiVFNSU5MCVBNiVFNCVCOCVCQSVFNyVBOSVCQSVFNyVBNCVCQSVFNCVCRSU4Qi5wbmc?x-oss-process=image/format,png) 對於程式碼的具體實現,可以讓其支援多型性。所以可以設計一個介面 Stack 定義上面這 5 個棧支援的操作,再設計一個類 ArrayStack 來實現這個介面。 > **對於 ArrayStack 這個類,實質上是基於之前實現的動態陣列類 Array 來實現的一個數組棧。因為對於棧而言,棧對應的操作是陣列的子集。可以把棧當成一個數組來看待。** > > **對於 Array 類的具體實現過程,可檢視另一篇 [文章](https://www.cnblogs.com/txxunmei/p/12604177.html) 。** #### 具體程式碼設計 在編寫棧的具體程式碼之前,先往工程中匯入之前實現的動態陣列類 Array,該類程式碼可從之前的文章中查閱, 因為要基於該類來實現陣列棧。 ![工程目錄示例1](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9teWJsb2dwaWN0dXJlLm9zcy1jbi1zaGVuemhlbi5hbGl5dW5jcy5jb20vJUU2JTk1JUIwJUU2JThEJUFFJUU3JUJCJTkzJUU2JTlFJTg0X0phdmFfJUU2JUEwJTg4JUU1JTkyJThDJUU5JTk4JTlGJUU1JTg4JTk3LyVFNSVCNyVBNSVFNyVBOCU4QiVFNyU5QiVBRSVFNSVCRCU5NSVFNyVBNCVCQSVFNCVCRSU4QjEucG5n?x-oss-process=image/format,png) ArrayStack 類的實現: > 因為在 Array 類中已經實現了很多運算元組的方法。所以對於 ArrayStack 類實現介面中的方法時,只需複用 Array 類中的方法即可。 基於 Array 類實現 ArrayStack 類也有一些好處: > **和 Array 一樣擁有了動態伸縮容量的功能**,我們不需要關心棧的容量是否夠用,因為容量會動態地進行擴大和縮小。 > > 對於一些非法變數的判斷直接複用了 Array 類中的程式碼,不需要重複編寫。 > > 同時,也可以為 ArrayStack 類新增一個介面中沒有的方法 getCapacity 提供給使用者獲取棧的容量。這個方法是這個類中特有的。 在實現 peek 方法之前,可以在 Array 類中擴充套件兩個新方法用於獲取陣列末尾和陣列首部的元素,方便在 ArrayStack 類和後續佇列的實現中直接複用。 ```java /** * 獲取陣列的最後一個元素 * * @return 返回陣列的最後一個元素 */ public E getLast() { return get(size - 1); } /** * 獲取陣列的第一個元素 * * @return 返回陣列的第一個元素 */ public E getFirst() { return get(0); } ``` Stack 介面類程式碼如下: ```java /** * 定義棧的基本操作的介面 * 支援泛型 * * @author 踏雪尋梅 * @date 2020/1/8 - 19:20 */ public interfa