數據結構day4——棧

目錄

一、棧的核心概念

什么是棧?

棧的核心特性

二、棧的基本操作

三、C 語言實現棧的兩種方式

1. 順序棧(基于數組實現)

實現代碼

順序棧的優缺點

2. 鏈式棧(基于鏈表實現)

實現代碼

鏈式棧的優缺點

四、棧的典型應用場景

五、總結


棧(Stack)作為一種經典的線性數據結構,因其 "后進先出"(LIFO)的特性,在編程領域有著廣泛的應用。無論是表達式求值、函數調用,還是括號匹配等場景,都能看到棧的身影。本文將帶你用 C 語言從零實現棧,深入理解其工作原理與實際應用。

一、棧的核心概念

什么是棧?

棧是一種限定僅在表尾進行插入和刪除操作的線性表。這里的 "表尾" 被稱為棧頂(Top),另一端則稱為棧底(Bottom)

棧的核心特性

棧最顯著的特點是后進先出(Last In First Out,LIFO)

  • 最后進入棧的元素,最先被取出
  • 最先進入棧的元素,最后被取出

生活中的棧示例:

  • 疊放的書本,只能從最上方取書
  • 瀏覽器的歷史記錄,"后退" 功能總是返回上一個訪問的頁面
  • 手機應用的任務棧,最近打開的應用最先被關閉

二、棧的基本操作

棧的操作圍繞棧頂進行,主要包括以下幾種:

操作名稱功能描述時間復雜度
initStack初始化棧O(1)
push向棧頂插入元素(入棧)O(1)
pop從棧頂移除元素(出棧)O(1)
peek獲取棧頂元素(不刪除)O(1)
isEmpty判斷棧是否為空O(1)
isFull判斷棧是否已滿O(1)
size獲取棧中元素個數O(1)

三、C 語言實現棧的兩種方式

在 C 語言中,棧通常有兩種實現方式:基于數組的順序棧和基于鏈表的鏈式棧。

1. 順序棧(基于數組實現)

順序棧使用固定大小的數組作為底層存儲,實現簡單且訪問高效。

實現代碼
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>#define MAX_SIZE 100  // 棧的最大容量// 棧的結構體定義
typedef struct {int data[MAX_SIZE];  // 存儲棧元素的數組int top;             // 棧頂指針(-1表示空棧)
} Stack;// 初始化棧
void initStack(Stack *stack) {stack->top = -1;  // 空棧狀態
}// 判斷棧是否為空
bool isEmpty(Stack *stack) {return stack->top == -1;
}// 判斷棧是否已滿
bool isFull(Stack *stack) {return stack->top == MAX_SIZE - 1;
}// 入棧操作
bool push(Stack *stack, int value) {if (isFull(stack)) {printf("棧已滿,無法入棧!\n");return false;}stack->data[++stack->top] = value;  // 先移動棧頂指針,再存入數據return true;
}// 出棧操作
bool pop(Stack *stack, int *value) {if (isEmpty(stack)) {printf("棧為空,無法出棧!\n");return false;}*value = stack->data[stack->top--];  // 先取出數據,再移動棧頂指針return true;
}// 獲取棧頂元素
bool peek(Stack *stack, int *value) {if (isEmpty(stack)) {printf("棧為空,無法獲取棧頂元素!\n");return false;}*value = stack->data[stack->top];return true;
}// 獲取棧的大小
int size(Stack *stack) {return stack->top + 1;  // 棧頂索引+1即為元素個數
}// 打印棧中所有元素
void printStack(Stack *stack) {if (isEmpty(stack)) {printf("棧為空!\n");return;}printf("棧元素(從棧底到棧頂):");for (int i = 0; i <= stack->top; i++) {printf("%d ", stack->data[i]);}printf("\n");
}// 主函數示例
int main() {Stack stack;initStack(&stack);int value;// 測試入棧push(&stack, 10);push(&stack, 20);push(&stack, 30);printStack(&stack);  // 輸出:10 20 30// 測試獲取棧頂元素if (peek(&stack, &value)) {printf("棧頂元素:%d\n", value);  // 輸出:30}// 測試出棧if (pop(&stack, &value)) {printf("出棧元素:%d\n", value);  // 輸出:30}printStack(&stack);  // 輸出:10 20printf("棧的大小:%d\n", size(&stack));  // 輸出:2printf("棧是否為空:%s\n", isEmpty(&stack) ? "是" : "否");  // 輸出:否return 0;
}
順序棧的優缺點
  • 優點:實現簡單,元素訪問速度快(數組隨機訪問特性)
  • 缺點
    • 容量固定,無法動態擴容(可能溢出)
    • 內存利用率不高(可能浪費空間)

2. 鏈式棧(基于鏈表實現)

鏈式棧使用鏈表節點存儲元素,可動態調整大小,內存利用率更高。

實現代碼
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>// 鏈表節點結構體
typedef struct Node {int data;               // 節點數據struct Node *next;      // 指向下一個節點的指針
} Node;// 棧的結構體(鏈式棧)
typedef struct {Node *top;  // 棧頂指針(指向鏈表頭節點)int size;   // 棧中元素個數
} LinkedStack;// 初始化棧
void initLinkedStack(LinkedStack *stack) {stack->top = NULL;stack->size = 0;
}// 判斷棧是否為空
bool isLinkedStackEmpty(LinkedStack *stack) {return stack->top == NULL;
}// 入棧操作
void pushLinkedStack(LinkedStack *stack, int value) {// 創建新節點Node *newNode = (Node *)malloc(sizeof(Node));if (newNode == NULL) {printf("內存分配失敗!\n");return;}newNode->data = value;newNode->next = stack->top;  // 新節點指向當前棧頂stack->top = newNode;        // 更新棧頂指針stack->size++;
}// 出棧操作
bool popLinkedStack(LinkedStack *stack, int *value) {if (isLinkedStackEmpty(stack)) {printf("棧為空,無法出棧!\n");return false;}Node *temp = stack->top;*value = temp->data;stack->top = stack->top->next;  // 更新棧頂指針free(temp);                     // 釋放節點內存stack->size--;return true;
}// 獲取棧頂元素
bool peekLinkedStack(LinkedStack *stack, int *value) {if (isLinkedStackEmpty(stack)) {printf("棧為空,無法獲取棧頂元素!\n");return false;}*value = stack->top->data;return true;
}// 打印棧中元素
void printLinkedStack(LinkedStack *stack) {if (isLinkedStackEmpty(stack)) {printf("棧為空!\n");return;}printf("棧元素(從棧頂到棧底):");Node *current = stack->top;while (current != NULL) {printf("%d ", current->data);current = current->next;}printf("\n");
}// 銷毀棧(釋放所有節點內存)
void destroyLinkedStack(LinkedStack *stack) {Node *temp;while (stack->top != NULL) {temp = stack->top;stack->top = stack->top->next;free(temp);}stack->size = 0;
}// 主函數示例
int main() {LinkedStack stack;initLinkedStack(&stack);int value;// 測試入棧pushLinkedStack(&stack, 100);pushLinkedStack(&stack, 200);pushLinkedStack(&stack, 300);printLinkedStack(&stack);  // 輸出:300 200 100// 測試獲取棧頂元素if (peekLinkedStack(&stack, &value)) {printf("棧頂元素:%d\n", value);  // 輸出:300}// 測試出棧if (popLinkedStack(&stack, &value)) {printf("出棧元素:%d\n", value);  // 輸出:300}printLinkedStack(&stack);  // 輸出:200 100printf("棧的大小:%d\n", stack.size);  // 輸出:2// 銷毀棧destroyLinkedStack(&stack);return 0;
}
鏈式棧的優缺點
  • 優點
    • 容量動態調整,無固定大小限制
    • 內存利用率高(按需分配)
  • 缺點
    • 實現相對復雜
    • 每個節點需要額外存儲指針,內存開銷略大
    • 訪問速度不如順序棧(鏈表順序訪問特性)

四、棧的典型應用場景

  1. 表達式求值:編譯器使用棧處理數學表達式(如后綴表達式轉換與計算)

  2. 括號匹配:檢查代碼中的括號是否正確配對(如()[]{}

    // 括號匹配示例函數
    bool isParenthesesValid(char *str) {Stack stack;initStack(&stack);int i = 0;while (str[i] != '\0') {if (str[i] == '(' || str[i] == '[' || str[i] == '{') {push(&stack, str[i]);  // 左括號入棧} else if (str[i] == ')' || str[i] == ']' || str[i] == '}') {if (isEmpty(&stack)) return false;  // 右括號多了char top;pop(&stack, &top);// 檢查括號是否匹配if ((str[i] == ')' && top != '(') ||(str[i] == ']' && top != '[') ||(str[i] == '}' && top != '{')) {return false;}}i++;}return isEmpty(&stack);  // 左括號是否多了
    }
    
  3. 函數調用:程序運行時,函數調用信息(返回地址、局部變量等)通過棧存儲

  4. 瀏覽器歷史記錄:實現 "前進"、"后退" 功能

  5. 撤銷操作:文本編輯器中的撤銷(Undo)功能

五、總結

棧作為一種基礎數據結構,雖然操作簡單,但應用場景廣泛。在 C 語言中,我們可以根據實際需求選擇實現方式:

  • 當元素數量固定且已知時,優先選擇順序棧(實現簡單、效率高)
  • 當元素數量不確定或動態變化時,優先選擇鏈式棧(內存利用率高)

掌握棧的原理與實現,不僅能幫助你解決實際編程問題,更為理解更復雜的數據結構(如樹、圖)奠定基礎。建議結合實際場景多做練習,加深對棧的理解與應用。

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

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

相關文章

用戶系統的架構設計與實現策略(二)

一個用戶系統除了基本的用戶業務功能&#xff0c;還應囊括用戶的權限設計及其實現。這本文中我們將探討一下關于用戶權限的設計與實現方法論。 簡介 在構建現代應用系統的過程中&#xff0c;很少有設計決策會像訪問控制機制那樣&#xff0c;對安全性、可擴展性和用戶體驗產生…

深度學習-邏輯回歸

邏輯回歸的目的 邏輯回歸只判斷樣本屬于正類的概率是多大&#xff0c;0-1之間 找到一組最佳的權重&#xff08;w1,w2,w3,…&#xff09; &#xff0c;b&#xff0c;使得模型預測的概率 P(Y1) 盡可能接近樣本的真實標簽&#xff08;1 或 0&#xff09;。 計算過程 前向傳播過程…

對象池模式:減少GC的Kotlin實戰指南

對象池模式通過對象復用機制&#xff0c;將對象生命周期從"創建-銷毀"轉變為"借出-歸還"&#xff0c;顯著減少GC壓力。下面通過完整實例展示其實現細節。 一、對象池工作原理圖解 #mermaid-svg-Edrz4np9hD6DJdNi {font-family:"trebuchet ms",v…

Java接口報錯:Packet for query is too large - 解決方案與架構思考

Java接口報錯&#xff1a;Packet for query is too large - 解決方案與架構思考 背景與技術原理解決方案體系&#xff08;擴展版&#xff09;一、MySQL服務端配置&#xff08;永久生效&#xff09;配置文件修改&#xff08;推薦生產環境&#xff09; 文件路徑參考Linux: /etc/m…

7月2日作業

思維導圖 一、創建一個進程扇 代碼 #include <25041head.h>int main(int argc, const char *argv[]) {pid_t pid;for(int i1;i<4;i){pidfork();if(pid>0){sleep(1);}if(pid0){printf("我是子進程%d:%d,父進程%d\n",i,getpid(),getppid());sleep(1);re…

設計模式(九)

職責鏈模式&#xff08;Chain of Responsibility&#xff09;詳解 一、核心概念 職責鏈模式將請求的發送者和接收者解耦&#xff0c;使多個對象都有機會處理請求。這些對象連接成一條鏈&#xff0c;請求沿著鏈傳遞&#xff0c;直到有一個對象處理它為止。該模式允許動態調整處…

左神算法之Zigzag方式打印矩陣

目錄 Zigzag方式打印矩陣1. 題目2. 解釋3. 思路4. 代碼5. 總結 Zigzag方式打印矩陣 1. 題目 用zigzag的方式打印矩陣&#xff0c;比如下面的矩陣&#xff1a; 0 1 2 3 4 5 6 7 8 9 10 11打印順序為&#xff1a;0 1 4 8 5 2 3 6 9 10 7 11 2. 解釋 Zigzag打印矩陣是指按照…

【前端批量下載圖片,并打包成壓縮包下載】

一、需求說明 我現在有個需求&#xff1a; 1.列表中有個下載按鈕&#xff0c;點擊下載&#xff0c;將列表中所有的圖片打成壓縮包&#xff0c;并下載 2.效果演示點擊查看效果 最終效果&#xff1a; 二、安裝下載插件 實現此功能需要兩個插件&#xff1a;jszip、file-saver …

NV133NV137美光固態閃存NV147NV148

NV133NV137美光固態閃存NV147NV148 美光固態閃存技術矩陣深度解析&#xff1a;NV133至NV148的全面較量 一、性能參數&#xff1a;數據高速公路的“車速”比拼 讀寫速度&#xff1a;從“鄉間小道”到“高鐵動脈” 美光NV系列固態閃存的核心競爭力在于其讀寫速度的躍升。以NV15…

從LLM到WM:大語言模型如何進化成具身世界模型?

1.引言這學期在方老師開設的《機器人大模型基礎和前沿》選修課上接觸并學習了具身智能方面的相關知識。作為交互組的組長&#xff0c;我和組員們在幻爾機器狗的功能開發上有切身的實踐與探索&#xff0c;在張江具身智能大會上&#xff0c;也見識到了前沿的技術和行業的發展現狀…

第十六屆藍橋杯C++B組國賽題解+復盤總結

文章目錄 寫在前面1、新型鎖2、互質藏卡3、數字輪盤4、斐波那契字符串5、項鏈排列6、藍橋星數字7、翻倍8、近似回文字符串9、子串去重10、涂格子 寫在前面 打了三年&#xff0c;第十六屆是我最后一次參加了&#xff0c;終于如愿以償國一啦。 這場的大多題目都補了&#xff0c;…

【TTS】2024-2025年主流開源TTS模型的綜合對比分析

以下是針對2024-2025年主流開源與商用TTS模型的綜合技術選型分析&#xff0c;結合GitHub熱度、功能特性、部署成本及中文支持等核心維度進行對比&#xff0c;并附詳細實踐建議。 一、開源TTS模型對比&#xff08;2024-2025年主流方案&#xff09; 模型名稱開源/廠商克隆支持中…

redis延時雙刪,為什么第一次刪除

Redis延時雙刪策略中第一次刪除的作用 在緩存與數據庫一致性方案中&#xff0c;"延時雙刪"&#xff08;Delayed Double-Delete&#xff09;是一種經典策略&#xff0c;其核心流程如下&#xff1a; 第一次刪除&#xff1a;更新數據庫前&#xff0c;先刪除緩存 更新數…

深度學習1(深度學習和機器學習的區別,神經網絡)

深度學習和機器學習的區別 深度學習和機器學習都是人工智能&#xff08;AI&#xff09;的重要分支&#xff0c;但它們在方法、應用場景和技術細節上有顯著區別。 機器學習通過算法讓計算機從數據中學習規律&#xff0c;并做出預測或決策。核心是特征工程&#xff08;人工提取數…

這才叫窗口查詢!TDEngine官方文檔沒講透的實戰玩法

第1章&#xff1a;你不知道的TDEngine窗口查詢——開局就不簡單 先別急著翻白眼&#xff0c;提到時間窗口查詢&#xff0c;可能你腦子里立馬浮現的就是那些常規套路&#xff1a;GROUP BY time_interval、FIRST()、LAST()&#xff0c;再加上點AVG()和MAX()&#xff0c;一鍋端。…

Day50 預訓練模型+CBAM模塊

目錄 一、resnet結構解析 二、CBAM放置位置的思考 三、針對預訓練模型的訓練策略 a.差異化學習率 b.三階段式解凍與微調 (Progressive Unfreezing) 四、嘗試對vgg16cbam進行微調策略 是否可以對于預訓練模型增加模塊來優化其效果&#xff0c;這里會遇到一個問題&#xff…

快速說一下TDD BDD DDD

基本概念 TDD&#xff08;測試驅動開發&#xff09;、BDD&#xff08;行為驅動開發&#xff09;和 DDD&#xff08;領域驅動設計&#xff09;是軟件開發領域中幾個重要的概念&#xff0c;它們各自有著獨特的側重點與應用場景&#xff0c;以下為你詳細介紹&#xff1a; 測試驅…

淺析基于深度學習算法的英文OCR技術工作原理及其應用場景

在數字化信息飛速發展的當下&#xff0c;大量的文本信息以各種形式存在&#xff0c;從傳統的紙質文檔到電子圖片中的文字內容。如何高效地將這些非結構化的文本轉化為計算機能夠理解和處理的格式&#xff0c;成為了提高信息處理效率的關鍵。英文 OCR&#xff08;Optical Charac…

AI時代SEO關鍵詞策略

內容概要 在人工智能&#xff08;AI&#xff09;驅動的新時代&#xff0c;搜索引擎優化&#xff08;SEO&#xff09;關鍵詞策略正迎來顛覆性變革。本篇文章將系統解析AI技術如何重塑關鍵詞研究、內容優化及流量提升的全過程&#xff0c;幫助企業實現高效可持續的在線曝光。通過…

免費一鍵自動化申請、續期、部署、監控所有 SSL/TLS 證書,ALLinSSL開源免費的 SSL 證書自動化管理平臺

目錄 一、前言二、ALLinSSL 簡介亮點核心功能 三、操作步驟部署安裝授權DNS服務商授權你的主機服務器自動化部署ssl測試自動申請ssl證書 一、前言 SSL證書是每個網站必備的&#xff0c;但是現在的免費的ssl證書有效期是3個月&#xff0c;以后CA/B Forum 調整 SSL 證書最長有效期…