數據結構之棧的2種實現方式(順序棧+鏈棧,附帶C語言完整實現源碼)

對于邏輯關系為“一對一”的數據,除了用順序表鏈表存儲外,還可以用棧結構存儲。

棧是一種“特殊”的線性存儲結構,它的特殊之處體現在以下兩個地方:
1、元素進棧和出棧的操作只能從一端完成,另一端是封閉的,如下圖所示:

棧存儲結構示意圖

圖 1 棧存儲結構示意圖

通常,我們將元素進棧的過程簡稱為“入棧”、“進棧”或者“壓棧”;將元素出棧的過程簡稱為“出棧”或者“彈棧”。

2、棧中無論存數據還是取數據,都必須遵循“先進后出”的原則,即最先入棧的元素最先出棧。以圖 1 的棧為例,很容易可以看出是元素 1 最先入棧,然后依次是元素 2、3、4 入棧。在此基礎上,如果想取出元素 1,根據“先進后出”的原則,必須先依次將元素 4、3、2 出棧,最后才能輪到元素 1 出棧。

我們習慣將棧的開口端稱為棧頂,封口端稱為棧底。例如在圖 1 中,元素 4 一側為棧頂,元素 1 一側為棧底,如圖 2 所示。

棧頂和棧底

圖 2 棧頂和棧底

由此我們可以對棧存儲結構下一個定義:棧一種“只能從一端存取元素,且存取過程必須遵循‘先進后出’原則”的線性存儲結構。

棧的具體實現

線性表類似,棧存儲結構也有兩種具體的實現方案:

  • 順序棧:用順序表存儲數據,數據存取的過程嚴格遵循棧結構的規定;
  • 鏈棧:用鏈表存儲數據,數據存儲的過程嚴格遵循棧結構的規定。

顯然,順序棧和鏈棧兩種實現方案,本質的區別仍然是順序表和鏈表之間的區別,即順序棧是將所有數據集中存儲,而鏈棧是將數據分散存放,元素之間的邏輯關系靠指針維系。

順序棧的具體實現

順序指的是用順序表實現的棧存儲結構,通過前面的學習我們知道,棧存儲結構存取數據元素必須遵守 "先進后出" 的原則。本節就給大家詳細講解如何使用順序表模擬棧結構,以及實現元素的入棧和出棧操作。

順序表和棧存儲數據的方式高度相似,只不過棧對數據的存取過程有特殊的限制,而順序表沒有。例如,我們使用順序表(用 a 數組表示)存儲?{1,2,3,4},存儲狀態如圖 1 所示:

順序表存儲 {1,2,3,4}

圖 1 順序表存儲 {1,2,3,4}

使用棧存儲結構存儲?{1,2,3,4},存儲狀態如圖 2 所示:

棧結構存儲 {1,2,3,4}

圖 2 棧結構存儲 {1,2,3,4}

對比圖 1 和圖 2 不難看出,用順序表模擬棧結構很簡單,只要將數據從數組下標為 0 的位置依次存儲即可。

從數組下標為 0 的模擬棧存儲數據是常用的方法,從其他數組下標處存儲數據也完全可以,這里只是為了方便初學者理解。

了解了順序表模擬實現棧存儲結構之后,接下來學習如何實現元素入棧和出棧的操作。

棧中存取元素,必須遵循“先進后出”的原則,因此若想將圖 1 中存儲的元素 1 從棧中取出,需依次先將元素 4、元素 3 和元素 2 從棧中取出,最后才能取出元素 1。

這里給出一種順序表模擬入棧和出棧的實現思路:定義一個實時記錄棧頂位置的變量(假設命名為 top),初始狀態下棧內無任何元素,整個棧是"空棧",top 的值為 -1。一旦有數據元素進棧,則 top 就做 +1 操作;反之,如果數據元素出棧,top 就做 -1 操作。

順序棧元素"入棧"

比如,還是模擬棧存儲?{1,2,3,4}?的過程。最初棧是"空棧",top 的值為 -1,如圖 3 所示:

空棧示意圖

圖 3 空棧示意圖

將元素 1 入棧,默認數組下標為 0 一端表示棧底,元素 1 存儲在數組 a[0] 處,同時 top 值 +1,如圖 4 所示:

模擬棧存儲元素 1

圖 4 模擬棧存儲元素 1

采用同樣的方式,依次將元素 2、3 和 4 入棧,最終 top 的值變成 3,如圖 5 所示:

模擬棧存儲{1,2,3,4}

圖 5 模擬棧存儲{1,2,3,4}

因此,C 語言實現代碼為:

//元素elem進棧,a為數組,top值為當前棧的棧頂位置
int push(int* a,int top,int elem){a[++top]=elem;return top;
}

代碼中的 a[++top]=elem,等價于先執行 ++top,再執行 a[top]=elem。

順序棧元素"出棧"

實際上,top 變量的設置對模擬數據的 "入棧" 操作沒有幫助,它是為實現數據的 "出棧" 操作做準備的。

比如,將圖 5 中的元素 2 出棧,則需要先將元素 4 和元素 3 依次出棧。需要注意的是,當有數據出棧時,要將 top 做 -1 操作。因此,元素 4 和元素 3 出棧的過程分別如圖 6a) 和 6b) 所示:

數據元素出棧

圖 6 數據元素出棧

元素 4 和元素 3 全部出棧后,元素 2 才能出棧。因此,使用順序表模擬數據出棧操作的 C 語言實現代碼為:

//數據元素出棧
int pop(int * a,int top){if (top == -1) {printf("空棧");return -1;}printf("彈棧元素:%d\n",a[top]);top--;return top;
}

代碼中的 if 語句是為了防止用戶做 "棧中已無數據卻還要做出棧操作" 的錯誤操作。細心的讀者還可能發現,出棧操作只是將 top 的值減 1,并沒有像圖 6 那樣將出棧元素從數組中手動刪除。這是因為,當有新的元素入棧后,新元素會將出棧元素覆蓋掉,所以不刪除出棧元素,也不會影響棧的正常使用,何必多此一舉。

總結

通過學習順序表模擬棧中數據入棧和出棧的操作,初學者完成了對順序棧的學習,這里給出順序棧及對數據基本操作的 C 語言完整代碼:

/*
* 源自 https://xiecoding.cn/ds/
*/
#include <stdio.h>
//元素elem進棧
int push(int* a, int top, int elem) {a[++top] = elem;return top;
}
//數據元素出棧
int pop(int* a, int top) {if (top == -1) {printf("空棧");return -1;}printf("彈棧元素:%d\n", a[top]);top--;return top;
}
int main() {int a[100];int top = -1;top = push(a, top, 1);top = push(a, top, 2);top = push(a, top, 3);top = push(a, top, 4);top = pop(a, top);top = pop(a, top);top = pop(a, top);top = pop(a, top);top = pop(a, top);return 0;
}

程序輸出結果為:

彈棧元素:4
彈棧元素:3
彈棧元素:2
彈棧元素:1
空棧

鏈棧的具體實現

是棧的一種實現方法,特指用鏈表實現棧存儲結構。

鏈棧的實現思路和順序棧類似,順序棧是將順序表(數組)的一端做棧底,另一端做棧頂;鏈棧也是如此,我們通常將鏈表的頭部做棧頂,尾部做棧底,如圖 1 所示:

鏈棧示意圖

圖 1 鏈棧示意圖

以鏈表的頭部做棧頂,最大的好處是:可以避免在實現元素 "入棧" 和 "出棧" 時做大量遍歷鏈表的耗時操作。有元素入棧時,只需要將其插入到鏈表的頭部;有元素出棧時,只需要從鏈表的頭部依次摘取結點。

因此,鏈棧實際上是一個采用頭插法插入或刪除數據的鏈表。

鏈棧元素入棧

例如,依次將 1、2、3、4 存儲到棧中,每個元素的入棧過程如圖 2 所示:

鏈棧元素依次入棧過程示意圖

圖 2 鏈棧元素依次入棧過程示意圖

C語言實現代碼為:

鏈棧元素出棧

在圖 2e) 所示鏈表的基礎上,假設將元素 3 從棧中取出,根據"先進后出"的原則,要先將元素 4 出棧,然后元素 3 才能出棧,整個操作過程如圖 3 所示:

鏈棧元素出棧示意圖

圖 3 鏈棧元素出棧示意圖

實現棧頂元素出棧的 C 語言代碼為:

//棧頂元素出鏈棧的實現函數
LineStack* pop(LineStack* stack) {if (stack) {//聲明一個新指針指向棧頂節點LineStack* p = stack;//更新頭指針stack = stack->next;printf("出棧元素:%d ", p->data);if (stack) {printf("新棧頂元素:%d\n", stack->data);}else {printf("棧已空\n");}free(p);}else {printf("棧內沒有元素");return stack;}return stack;
}

代碼中通過使用 if 判斷語句,避免了用戶執行"棧已空卻還要數據出棧"錯誤操作。

總結

本節,通過采用頭插法操作數據的單鏈表實現了鏈棧結構,這里給出鏈棧及基本操作的C語言完整代碼:

/*
* 源自 https://xiecoding.cn/ds/
*/
#include <stdio.h>
#include <stdlib.h>
//鏈表中的節點結構
typedef struct lineStack {int data;struct lineStack* next;
}LineStack;
//stack為當前的鏈棧,a表示入棧元素
LineStack* push(LineStack* stack, int a) {//創建存儲新元素的節點LineStack* line = (LineStack*)malloc(sizeof(LineStack));line->data = a;//新節點與頭節點建立邏輯關系line->next = stack;//更新頭指針的指向stack = line;return stack;
}//棧頂元素出鏈棧的實現函數
LineStack* pop(LineStack* stack) {if (stack) {//聲明一個新指針指向棧頂節點LineStack* p = stack;//更新頭指針stack = stack->next;printf("出棧元素:%d ", p->data);if (stack) {printf("新棧頂元素:%d\n", stack->data);}else {printf("棧已空\n");}free(p);}else {printf("棧內沒有元素");return stack;}return stack;
}int main() {LineStack* stack = NULL;stack = push(stack, 1);stack = push(stack, 2);stack = push(stack, 3);stack = push(stack, 4);stack = pop(stack);stack = pop(stack);stack = pop(stack);stack = pop(stack);stack = pop(stack);return 0;
}

程序運行結果為:

彈棧元素:4 棧頂元素:3
彈棧元素:3 棧頂元素:2
彈棧元素:2 棧頂元素:1
彈棧元素:1 棧已空
棧內沒有元素

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/74086.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/74086.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/74086.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Camera2 API拍照失敗問題實錄:從錯誤碼到格式轉換的排坑之旅

一、問題背景 在開發基于Camera2 API的相機應用時&#xff0c;我們遇到了一個棘手的問題&#xff1a;預覽功能在所有設備上工作正常&#xff0c;但在某特定安卓設備上點擊拍照按鈕后無任何響應。值得注意的是&#xff0c;使用舊版Camera API時該設備可以正常拍照。本文記錄了完…

Jmeter舊版本如何下載

1.Jmeter最新版本下載位置 https://jmeter.apache.org/download_jmeter.cgi2.Jmeter舊版本下載位置 https://archive.apache.org/dist/jmeter/binaries穩定版本&#xff1a;5.4.1

css-grid布局

文章目錄 1、布局2、網格軌道3、間距Gap4、網格線5、網格別名 當一個 HTML 元素將 display 屬性設置為 grid 或 inline-grid 后&#xff0c;它就變成了一個網格容器&#xff0c;這個元素的所有直系子元素將成為網格元素。 1、布局 啟用grid布局類似與flex布局&#xff0c;不過g…

SolidWorks使用顯卡教程

操作步驟&#xff1a; 打開注冊表編輯器 按下鍵盤上的 Win R 組合鍵&#xff0c;輸入 regedit 并按回車鍵&#xff0c;打開注冊表編輯器。 導航到顯卡信息路徑 在注冊表中依次展開以下路徑&#xff1a; plaintext HKEY_CURRENT_USER\Software\SolidWorks\SOLIDWORKS 2021\Per…

【C++11】左值引用、右值引用、移動語義和完美轉發

&#x1f984;個人主頁:修修修也 &#x1f38f;所屬專欄:C ??操作環境:Visual Studio 2022 目錄 &#x1f4cc;左值引用和右值引用 &#x1f38f;左值和左值引用 &#x1f38f;右值和右值引用 &#x1f4cc;左值引用和右值引用比較 &#x1f38f;左值引用 &#x1f38f;右值…

麒麟系列Linux發行版探秘

以下內容摘自《銀河麒麟操作系統進階應用》一書。 銀河麒麟操作系統&#xff08;Kylin&#xff09; 銀河麒麟&#xff08;Kylin&#xff09;操作系統是中國自主研發的一款基于Linux內核的操作系統。它的發展歷程可以追溯到2002年&#xff0c;最初由國防科技大學主導研發&…

【機密計算頂會解讀】11:ACAI——使用 Arm 機密計算架構保護加速器執行

導讀&#xff1a;本文介紹ACAI&#xff0c;其構建一個基于CCA的解決方案&#xff0c;使得機密虛擬機能夠安全地使用加速器&#xff0c;同時保持與現有應用程序的兼容性和安全性&#xff0c;能夠實現對加速器的安全訪問。 原文鏈接&#xff1a;ACAI: Protecting Accelerator Ex…

第一天 UnityShader的結構

Shader初學者的學習筆記 第一天 Unity Shader的結構 文章目錄 Shader初學者的學習筆記前言一、Unity Shader結構二、Unity Shader結構解析① Properties② Tags③ RenderSetup(可選狀態)④ Name⑤ [Tags]⑥ [RenderSetup]⑦ 頂點著色器和片元著色器的代碼 (Unity最聰明的孩子)…

VL開源模型實現文本生成圖片

一、 基礎知識 根據描述生成圖片的視覺-語言模型&#xff08;Vision-Language Models, VL 模型&#xff09;是近年來多模態生成領域的熱點研究方向。這些模型能夠根據自然語言描述生成高質量的圖像&#xff0c;廣泛應用于藝術創作、設計輔助、虛擬場景構建等領域。 1 根據描述…

【Java SE】抽象類/方法、模板設計模式

目錄 1.抽象類/方法 1.1 基本介紹 1.2 語法格式 1.3 使用細節 2. 模板設計模式&#xff08;抽象類使用場景&#xff09; 2.1 基本介紹 2.2 具體例子 1.抽象類/方法 1.1 基本介紹 ① 當父類的某些方法&#xff0c;需要聲明&#xff0c;但是又不確定如何實現時&#xff…

【人工智能】LM Studio 的 GPU 加速:釋放大模型推理潛能的極致優化

《Python OpenCV從菜鳥到高手》帶你進入圖像處理與計算機視覺的大門! 解鎖Python編程的無限可能:《奇妙的Python》帶你漫游代碼世界 隨著大語言模型(LLM)的廣泛應用,其推理效率成為限制性能的關鍵瓶頸。LM Studio 作為一個輕量級機器學習框架,通過 GPU 加速顯著提升了大…

深度學習:從零開始的DeepSeek-R1-Distill有監督微調訓練實戰(SFT)

原文鏈接&#xff1a;從零開始的DeepSeek微調訓練實戰&#xff08;SFT&#xff09; 微調參考示例&#xff1a;由unsloth官方提供https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Qwen2.5_(7B)-Alpaca.ipynbhttps://colab.research.google.com/git…

流暢如絲:利用requestAnimationFrame優化你的Web動畫體驗

requestAnimationFrame 是前端開發中用于優化動畫性能的 API。它允許瀏覽器在下一次重繪之前執行指定的回調函數&#xff0c;通常用于實現平滑的動畫效果。 1.作用 優化性能&#xff1a;requestAnimationFrame 會根據瀏覽器的刷新率&#xff08;通常是 60Hz&#xff0c;即每秒…

【pytest框架源碼分析五】pytest插件的注冊流程

前文介紹到pytest整體是運用插件來實現其運行流程的。這里仔細介紹下具體過程。 首先進入main方法 def main(args: list[str] | os.PathLike[str] | None None,plugins: Sequence[str | _PluggyPlugin] | None None, ) -> int | ExitCode:"""Perform an i…

IoTDB日志提示Too many open files

問題 時序數據庫 IoTDB 1.3.3 版本 IoTDB 執行查詢操作失敗&#xff0c;日志打印提示 Too many open files。通過命令查看打開文件數&#xff0c;結果如下&#xff1a; [root0002 DataReceiver]# lsof|grep 28347|wc -l DataNode 55444 [root0002 DataReceiver]# lsof|g…

prometheus 添加alertmanager添加dingtalk機器人告警

1、dingtalk創建機器人,目前我們采用加白名單的方式校驗 2、定位到如下圖 test結果如下

C 語 言 --- 操 作 符 2

C 語 言 --- 操 作 符 2 移 位 操 作 符定 義原 碼 補 碼 和 反 碼左 移&#xff08;<<&#xff09;右 移&#xff08;>>&#xff09;算 術 右 移邏 輯 右 移 按 位 與、按 位 或、和 按 位 異 或按 位 與按 位 或按 位 異 或 邏 輯 反 操 作負 值 操 作按 位 取 反…

基于Spring Boot的公司資產網站的設計與實現(LW+源碼+講解)

專注于大學生項目實戰開發,講解,畢業答疑輔導&#xff0c;歡迎高校老師/同行前輩交流合作?。 技術范圍&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬蟲、數據可視化、安卓app、大數據、物聯網、機器學習等設計與開發。 主要內容&#xff1a;…

零碳工廠能源管理系統的核心技術與應用實踐

零碳工廠能源管理系統是一種高效的解決方案&#xff0c;旨在優化能源使用并減少碳排放&#xff0c;以幫助工廠實現低碳或零碳的生產目標。以下是該系統的詳細構成和功能&#xff1a; 1. 核心組件 傳感器和監測設備&#xff1a;用于實時監測工廠內的能源使用情況&#xff0c;包…

美攝接入DeepSeek等大模型,用多模態融合重構視頻創作新邊界!

今年以來&#xff0c;DeepSeek憑借其強大的深度推理分析能力&#xff0c;在AI領域掀起新的熱潮。美攝科技快速響應市場需求&#xff0c;迅速接入以DeepSeek、通義千問、商湯、文心一言為代表的大模型&#xff0c;為企業視頻創作生產帶來全新體驗。 傳統視頻創作面臨著同質化、…