怎樣在 C 語言中實現棧?

🍅關注博主🎗? 帶你暢游技術世界,不錯過每一次成長機會!
📙C 語言百萬年薪修煉課程 通俗易懂,深入淺出,匠心打磨,死磕細節,6年迭代,看過的人都說好。

分割線

文章目錄

  • 如何在 C 語言中實現棧
  • 一、棧的基本概念
  • 二、棧的操作
  • 三、使用數組實現棧
  • 四、使用鏈表實現棧
  • 五、兩種實現方式的比較
    • (一)空間復雜度
    • (二)時間復雜度
    • (三)靈活性
    • (四)適用場景
  • 六、棧的應用場景
    • (一)函數調用
    • (二)表達式求值
    • (三)括號匹配
    • (四)回溯算法
  • 七、總結

分割線


如何在 C 語言中實現棧

在 C 語言中,棧(Stack)是一種常見的數據結構,它遵循后進先出(Last In First Out,LIFO)的原則。這意味著最后添加到棧中的元素將首先被移除。

一、棧的基本概念

棧是一種線性數據結構,具有以下特點:

  1. 棧頂(Top):棧的頂部元素,是進行插入和刪除操作的一端。
  2. 棧底(Bottom):棧的底部元素,是相對固定的一端。

二、棧的操作

常見的棧操作包括:

  1. push:將元素壓入棧頂。
  2. pop:彈出棧頂元素。
  3. peek(或者 top):獲取棧頂元素但不彈出。
  4. isEmpty:判斷棧是否為空。

三、使用數組實現棧

以下是使用數組來實現棧的 C 語言代碼示例:

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>#define MAX_SIZE 100typedef struct {int items[MAX_SIZE];int top;
} 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;
}// 壓入元素到棧
void push(Stack *stack, int element) {if (isFull(stack)) {printf("Stack Overflow!\n");return;}stack->items[++stack->top] = element;
}// 彈出棧頂元素
int pop(Stack *stack) {if (isEmpty(stack)) {printf("Stack Underflow!\n");return -1;}int element = stack->items[stack->top];stack->top--;return element;
}// 獲取棧頂元素但不彈出
int peek(Stack *stack) {if (isEmpty(stack)) {printf("Stack is empty!\n");return -1;}return stack->items[stack->top];
}int main() {Stack stack;initStack(&stack);push(&stack, 10);push(&stack, 20);push(&stack, 30);printf("Top element: %d\n", peek(&stack));int poppedElement = pop(&stack);if (poppedElement!= -1) {printf("Popped element: %d\n", poppedElement);}printf("Top element after pop: %d\n", peek(&stack));return 0;
}

在上述代碼中:

  • initStack 函數用于初始化棧,將棧頂指針設置為 -1,表示棧為空。
  • isEmpty 函數通過檢查棧頂指針是否為 -1 來判斷棧是否為空。
  • isFull 函數通過檢查棧頂指針是否達到數組的最大索引來判斷棧是否已滿。
  • push 函數在壓入元素之前,先檢查棧是否已滿。如果未滿,將元素添加到棧頂,并更新棧頂指針。
  • pop 函數在彈出元素之前,先檢查棧是否為空。如果不為空,返回棧頂元素,并更新棧頂指針。
  • peek 函數返回棧頂元素,但不修改棧的狀態。

四、使用鏈表實現棧

除了使用數組,我們還可以使用鏈表來實現棧。以下是使用鏈表實現棧的 C 語言代碼示例:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>typedef struct Node {int data;struct Node *next;
} Node;typedef struct {Node *top;
} Stack;// 初始化棧
void initStack(Stack *stack) {stack->top = NULL;
}// 判斷棧是否為空
bool isEmpty(Stack *stack) {return stack->top == NULL;
}// 壓入元素到棧
void push(Stack *stack, int element) {Node *newNode = (Node *)malloc(sizeof(Node));if (newNode == NULL) {printf("Memory allocation failed!\n");return;}newNode->data = element;newNode->next = stack->top;stack->top = newNode;
}// 彈出棧頂元素
int pop(Stack *stack) {if (isEmpty(stack)) {printf("Stack Underflow!\n");return -1;}Node *temp = stack->top;int element = temp->data;stack->top = stack->top->next;free(temp);return element;
}// 獲取棧頂元素但不彈出
int peek(Stack *stack) {if (isEmpty(stack)) {printf("Stack is empty!\n");return -1;}return stack->top->data;
}// 打印棧
void printStack(Stack *stack) {Node *current = stack->top;printf("Stack: ");while (current!= NULL) {printf("%d ", current->data);current = current->next;}printf("\n");
}int main() {Stack stack;initStack(&stack);push(&stack, 10);push(&stack, 20);push(&stack, 30);printStack(&stack);int poppedElement = pop(&stack);if (poppedElement!= -1) {printf("Popped element: %d\n", poppedElement);}printStack(&stack);printf("Top element: %d\n", peek(&stack));return 0;
}

在這個鏈表實現的棧中:

  • 每個節點包含數據和指向下一個節點的指針。
  • initStack 函數將棧頂指針初始化為 NULL,表示空棧。
  • push 函數創建一個新節點,將其數據設置為要壓入的元素,并將其鏈接到當前棧頂節點之前,更新棧頂指針。
  • pop 函數如果棧不為空,刪除棧頂節點,返回其數據,并更新棧頂指針,同時釋放已刪除節點的內存。
  • peek 函數返回棧頂節點的數據。
  • printStack 函數用于打印棧中的所有元素。

五、兩種實現方式的比較

(一)空間復雜度

  • 數組實現:在創建棧時需要預先分配固定大小的連續內存空間。如果棧的實際使用空間小于預分配的空間,會造成一定的內存浪費;如果棧的實際使用空間超過預分配的空間,還需要進行擴容操作,可能涉及到數據的復制和內存的重新分配,增加了額外的開銷。
  • 鏈表實現:每個節點在需要時動態分配內存,不會造成內存的預先浪費。但是,每個節點除了存儲數據外,還需要額外的空間來存儲指針,因此會有一些額外的內存開銷。

(二)時間復雜度

  • 數組實現:
    • push 操作:在棧未滿的情況下,時間復雜度為 O(1)
    • pop 操作:在棧不為空的情況下,時間復雜度為 O(1)
    • 訪問棧頂元素:時間復雜度為 O(1)
  • 鏈表實現:
    • push 操作:需要創建新節點并更新指針,時間復雜度為 O(1)
    • pop 操作:需要刪除節點并更新指針,時間復雜度為 O(1)
    • 訪問棧頂元素:時間復雜度為 O(1)

總體來說,兩種實現方式在常見操作的時間復雜度上是相同的。

(三)靈活性

  • 數組實現:由于數組的大小是固定的,在需要動態調整棧的大小時,操作相對復雜。
  • 鏈表實現:可以更靈活地添加和刪除元素,不需要考慮固定大小的限制。

(四)適用場景

  • 數組實現:適用于事先知道棧的最大規模,并且對內存使用較為敏感的場景。
  • 鏈表實現:適用于無法確定棧的最大規模,或者需要更靈活地管理棧的空間的場景。

六、棧的應用場景

(一)函數調用

在計算機程序中,當一個函數調用另一個函數時,系統會將當前函數的執行上下文(包括參數、局部變量、返回地址等)壓入棧中。當被調用函數執行完畢后,系統從棧中彈出之前保存的執行上下文,恢復到調用函數繼續執行。

(二)表達式求值

在對算術表達式進行求值時,可以使用棧來存儲操作數和運算符。通過按照特定的規則進行入棧和出棧操作,可以實現表達式的正確求值。

(三)括號匹配

檢查一段包含括號(如 ()[]{})的文本中括號是否匹配,可以使用棧來輔助判斷。遇到左括號入棧,遇到右括號時與棧頂的左括號進行匹配,如果匹配成功則彈出棧頂元素,否則表示括號不匹配。

(四)回溯算法

在一些需要回溯的算法中,如深度優先搜索、八皇后問題等,可以使用棧來保存中間狀態,以便在需要時進行回溯。

七、總結

在 C 語言中,我們可以使用數組或鏈表來實現棧。兩種實現方式各有優缺點,應根據具體的應用場景選擇合適的實現方式。理解棧的概念和實現原理對于解決許多編程問題非常有幫助,并且在實際的開發中有著廣泛的應用。


分割線

🎉相關推薦

  • 📙C 語言百萬年薪修煉課程 通俗易懂,深入淺出,匠心打磨,死磕細節,6年迭代,看過的人都說好。
  • 🍅博客首頁-關注博主🎗? 帶你暢游技術世界,不錯過每一次成長機會!
  • 📙CSDN專欄-C語言修煉
  • 📙技術社區-墨松科技

C語言



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

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

相關文章

動手學深度學習(Pytorch版)代碼實踐 -循環神經網絡-55循環神經網絡的從零開始實現和簡潔實現

55循環神經網絡的實現 1.從零開始實現 import math import torch from torch import nn from torch.nn import functional as F from d2l import torch as d2l import matplotlib.pyplot as plt import liliPytorch as lp# 讀取H.G.Wells的時光機器數據集 batch_size, num_ste…

開發個人Ollama-Chat--7 服務部署

開發個人Ollama-Chat–7 服務部署 服務部署 go-ChatGPT項目涉及的中間件服務較多&#xff0c;以下部署文件目錄&#xff1a; |-- chat-api | |-- etc | | -- config.yaml | -- logs |-- chat-rpc | |-- etc | | -- config.yaml | -- logs |-- docker-compos…

ElasticSearch第一天

學習目標&#xff1a; 能夠理解ElasticSearch的作用能夠安裝ElasticSearch服務能夠理解ElasticSearch的相關概念能夠使用Postman發送Restful請求操作ElasticSearch能夠理解分詞器的作用能夠使用ElasticSearch集成IK分詞器能夠完成es集群搭建 第一章 ElasticSearch簡介 1.1 什么…

windows 中的 Nsight Systems 通過ssh 鏈接分析 Linux 中的cuda程序性能

1&#xff0c;Linux 環境 安裝 ssh-server $ sudo apt install openssh-server 安裝較新版本的 cuda sdk 下載cuda-samples github repo 編輯修改 ssh 配置&#xff1a; $ sudo vim /etc/ssh/sshd_config 刪除相關注釋&#xff0c;修改后如下&#xff1a; Port 22 Addres…

只會vue的前端開發工程師是不是不能活了?最近被一個flutter叼了

**Vue與Flutter&#xff1a;前端開發的新篇章** 在前端開發的世界里&#xff0c;Vue.js和Flutter無疑是兩顆璀璨的明星。Vue以其輕量級、易上手的特點吸引了大量前端開發者的青睞&#xff0c;而Flutter則以其跨平臺、高性能的優勢迅速崛起。那么&#xff0c;對于只會Vue的前端…

【深度學習基礎】環境搭建 linux系統下安裝pytorch

目錄 一、anaconda 安裝二、創建pytorch1. 創建pytorch環境&#xff1a;2. 激活環境3. 下載安裝pytorch包4. 檢查是否安裝成功 一、anaconda 安裝 具體的安裝說明可以參考我的另外一篇文章【環境搭建】Linux報錯bash: conda: command not found… 二、創建pytorch 1. 創建py…

OceanBase:引領下一代分布式數據庫技術的前沿

OceanBase的基本概念 定義和特點 OceanBase是一款由螞蟻金服開發的分布式關系數據庫系統&#xff0c;旨在提供高性能、高可用性和強一致性的數據庫服務。它結合了關系數據庫和分布式系統的優勢&#xff0c;適用于大規模數據處理和高并發業務場景。其核心特點包括&#xff1a; …

【考研數學】25張宇強化36講測評及強化階段注意事項

張宇新版36講創新真的很大&#x1f979; 引入了很多張宇老師認為對大家解題幫助很大的技巧和知識點&#xff0c;但是也有人認為是多余的。 張宇老師新版36講第一講就講了整整8個小時&#xff01;&#x1f62d; 大家想想&#xff0c;自己有那個時間去吃透36講嗎&#xff1f;如果…

python調用阿里云匯率接口

整體請求流程 介紹&#xff1a; 本次解析通過阿里云云市場的云服務來實現程序中對貨幣匯率實時監控&#xff0c;首先需要準備選擇一家可以提供匯率查詢的商品。 https://market.aliyun.com/apimarket/detail/cmapi00065831#skuyuncode5983100001 步驟1: 選擇商品 如圖點擊…

debian 12 Install

debian 前言 Debian是一個基于Linux內核的自由和開放源代碼操作系統&#xff0c;由全球志愿者組成的Debian項目維護和開發。該項目始于1993年&#xff0c;由Ian Murdock發起&#xff0c;旨在創建一個完整的、基于Linux的自由軟件操作系統。 debian download debian 百度網盤…

分布式應用系統設計:即時消息系統

即時消息(IM)系統&#xff0c;涉及&#xff1a;站內消息系統 組件如下&#xff1b; 客戶端&#xff1a; WEB頁面&#xff0c;IM桌面客戶端。通過WebSocket 跟ChatService后端服務連接 Chat Service&#xff1a; 提供WebSocket接口&#xff0c;并保持跟“客戶端”狀態的維護。…

會聲會影分割音頻怎么不能用 會聲會影分割音頻方法 會聲會影視頻制作教程 會聲會影下載免費中文版2023

將素材中的音頻分割出來&#xff0c;對聲音部分進行單獨編輯&#xff0c;是剪輯過程中的常用操作。會聲會影視頻剪輯軟件在分割音頻后&#xff0c;還可以對聲音素材進行混音編輯、音頻調節、添加音頻濾鏡等操作。有關會聲會影分割音頻怎么不能用&#xff0c;會聲會影分割音頻方…

如何快速制作您的數據可視化大屏?

數據大屏可視化主要就是借助圖形&#xff0c;利用生動、直觀的形式展示出數據信息的具體數值&#xff0c;使得使用者短時間內更加直觀的接受到大量信息。數據大屏以直觀、高度視覺沖擊力的方式向受眾揭示數據背后隱藏的規律&#xff0c;傳達數據價值。其以圖形化的形式呈現數據…

視頻使用操作說明書-T80005系列視頻編碼器如何對接海康NVR硬盤錄像機,包括T80005系列高清HDMI編碼器、4K超高清HDMI編碼器

視頻使用操作說明書-T80005系列視頻編碼器如何對接海康NVR硬盤錄像機&#xff0c;包括T80005系列高清HDMI編碼器、4K超高清HDMI編碼器。 視頻使用操作說明書-T80005系列視頻編碼器如何對接海康NVR硬盤錄像機&#xff0c;包括T80005系列高清HDMI編碼器、4K超高清HDMI編碼器 同三…

全國產T3+FPGA的SPI與I2C通信方案分享

近年來&#xff0c;隨著中國新基建、中國制造2025規劃的持續推進&#xff0c;單ARM處理器越來越難勝任工業現場的功能要求&#xff0c;特別是如今能源電力、工業控制、智慧醫療等行業&#xff0c;往往更需要ARM FPGA架構的處理器平臺來實現例如多路/高速AD采集、多路網口、多路…

Tomcat多實例

一、Tomcat多實例 Tomcat多實例是指在同一臺服務器上運行多個獨立的tomcat實例&#xff0c;每個tomcat實例都具有獨立的配置文件、日志文件、應用程序和端口&#xff0c;通過配置不同的端口和文件目錄&#xff0c;可以實現同時運行多個獨立的Tomcat服務器&#xff0c;每個服務…

element-plus 按需導入問題 404等問題

場景 新開一個項目&#xff0c;需要用element-plus這個ui庫&#xff0c;使用按需引入。 這是我項目的一些版本號 "element-plus": "^2.7.6","vue": "^3.2.13","vue-router": "^4.0.3",過程&#xff08;看解決方法…

FastGPT+OneAI接入網絡模型

文章目錄 FastGPT連接OneAI接入網絡模型1.準備工作2.開始部署2.1下載 docker-compose.yml2.2修改docker-compose.yml里的參數 3.打開FastGPT添加模型3.1打開OneAPI3.2接入網絡模型3.3重啟服務 FastGPT連接OneAI接入網絡模型 1.準備工作 本文檔參考FastGPT的官方文檔 主機ip接…

JVM是如何管理內存的?圖文詳解GC垃圾回收算法

前言&#xff1a;在C/C中對于變量的內存空間一般都是由程序員手動進行管理的&#xff0c;往往會伴隨著大量的 malloc 和 free 操作&#xff0c;常常會有很多問題困擾開發者&#xff0c;這個代碼會不會發生內存泄漏&#xff1f;會不會重復釋放內存&#xff1f;但是在Java開發中我…

基于企業微信第三方接口開發,移除群成員通知

移除群成員通知 返回示例 {"flag": 0, "receiver": 0, "sender_name": "", "is_room": 1, "server_id": 15318083, "send_time": 1687688952, "sender": 1688855749266556, "referid&…