【數據結構】——棧(Stack)的原理與實現

目錄

  • 一. 棧的認識
    • 1. 棧的基本概念
    • 2.棧的基本操作
  • 二. 棧的核心優勢
    • 1. 高效的時間復雜度
    • 2. 簡潔的邏輯設計
    • 3. 內存管理優化
  • 三. 棧的代碼實現
    • 1.棧的結構定義
    • 2. 棧的初始化
    • 3. 入棧 (動態擴容)
    • 4. 出棧
    • 5. 取棧頂數據
    • 6. 判斷棧是否為空
    • 7. 獲取棧的數據個數
    • 8.銷毀
    • 9.完整代碼展示
  • 總結

一. 棧的認識

1. 棧的基本概念

棧是一種特殊的線性表,只允許在固定的一端進行插入和刪除元素的操作。進行數據插入和刪除操作的一端稱為棧頂,另一端稱為棧底。棧中的數據元素遵循后進先出的原則。

  • 壓棧: 棧的插入操作叫做進棧/壓棧/入棧,入數據的元素在棧頂。
  • 出棧: 棧的出棧也叫刪除操作,出數據也在棧頂。

在這里插入圖片描述

2.棧的基本操作

操作描述時間復雜度
Push(x)將元素x壓入棧頂O(1)
Pop()出棧彈出元素O(1)
Top()返回棧頂元素不出棧O(1)
Empty()檢查棧是否為空O(1)
Size()返回棧中元素數量O(1)

二. 棧的核心優勢

1. 高效的時間復雜度

  • 入棧、出棧、取棧頂均為常數時間O(1)操作,適合高頻調用場景。
  • 專注“頂部”操作,避免不必要的復雜度。
  • 對比其他數據結構:
    數組:隨機訪問快O(1),但插入刪除中間元素移動數據O(n);
    鏈表:插入刪除中間元素快O(1),但隨機訪問慢O(n);

2. 簡潔的邏輯設計

  • 減少代碼的復雜度,設計更簡單。
  • 通過壓棧和出棧自動維護操作順序,無需手動跟蹤索引指針。

3. 內存管理優化

  • 局部性原理:棧操作集中在頂部,數據訪問具有空間局部性,利用CPU緩存命中。
  • 動態擴容策略:棧實現如動態數組通過按需擴容平衡時間和空間效率。

三. 棧的代碼實現

1.棧的結構定義

typedef struct Stack
{STDataType* a; // 動態數組,存儲棧里的元素int top;       // 棧頂指針(初始為0,表示空棧)int capacity; // 棧的最大容量
}ST;
  • a:用指針指向一塊內存。
  • top:指向當前棧頂的元素初始為0,表示空棧
  • capacity:棧的最大容量

2. 棧的初始化

//初始化
void STInit(ST* pst)
{pst->a = NULL;//top指向棧頂數據的下一個位置pst->capacity = pst->top = 0;
}
  • 初始化指針賦值為NULL,capacity和top賦值為0。

3. 入棧 (動態擴容)

//入棧
void STPush(ST* pst, STDataType x)
{assert(pst);if (pst->capacity == pst->top){int newcapacity = pst->top == 0 ? 4 : 2 * pst->capacity;STDataType* newnode = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));if (newnode == NULL){perror("realloc fail");exit(-1);}pst->a = newnode;pst->capacity = newcapacity;}pst->a[pst->top] = x;pst->top++;
}
  • 當capacity等于top時,如果為空則開辟4個空間,不為空時開辟當前空間的二倍。
  • 將插入的值先存放在top下標位置再top++。

4. 出棧

//出棧
void STPop(ST* pst)
{assert(pst && pst->top>0);pst->top--;
}
  • 直接top- - 限制訪問完成出棧。

5. 取棧頂數據

//取棧頂數據
STDataType STTop(ST* pst)
{assert(pst && pst->top>0);return pst->a[pst->top - 1];
}
  • top的位置是在最后一個元素的下一個位置,所以取棧頂數據直接取top減1的下標。

6. 判斷棧是否為空

//判空
bool STEmpty(ST* pst)
{assert(pst);return pst->top == 0;
}
  • 返回值是bool類型,如果top == 0則返回true。

7. 獲取棧的數據個數

//獲取數據個數
int STSize(ST* pst)
{assert(pst);return pst->top;
}
  • 因為棧的位置是從0開始的,所以直接返回top就是棧內部的數據個數。

8.銷毀

//銷毀
void STDestroy(ST* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->top = pst->capacity = 0;
}
  • 釋放掉開辟的空間,將開辟的空間置為NULL,把top和capacity也置為空。

9.完整代碼展示

  • Stack.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include<stdbool.h>typedef int STDataType;typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;//初始化
void STInit(ST* pst);//銷毀
void STDestroy(ST* pst);//入棧
void STPush(ST* pst, STDataType x);//出棧
void STPop(ST* pst);//取棧頂數據
STDataType STTop(ST* pst);//判空
bool STEmpty(ST* pst);//獲取數據個數
int STSize(ST* pst);
  • Stack.c
#include "Stack.h"//初始化
void STInit(ST* pst)
{pst->a = NULL;//top指向棧頂數據的下一個位置pst->capacity = pst->top = 0;
}//銷毀
void STDestroy(ST* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->top = pst->capacity = 0;
}//入棧
void STPush(ST* pst, STDataType x)
{assert(pst);if (pst->capacity == pst->top){int newcapacity = pst->top == 0 ? 4 : 2 * pst->capacity;STDataType* newnode = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));if (newnode == NULL){perror("realloc fail");exit(-1);}pst->a = newnode;pst->capacity = newcapacity;}pst->a[pst->top] = x;pst->top++;
}//出棧
void STPop(ST* pst)
{assert(pst && pst->top>0);pst->top--;
}//取棧頂數據
STDataType STTop(ST* pst)
{assert(pst && pst->top>0);return pst->a[pst->top - 1];
}//判空  等于0就為真
bool STEmpty(ST* pst)
{assert(pst);return pst->top == 0;
}//獲取數據個數
int STSize(ST* pst)
{assert(pst);return pst->top;
}

在這里插入圖片描述
入棧順序為:1 2 3 4 5
出棧順序為:5 4 3 2 1

總結

根據上述講解,相信大家對棧有更深層的理解了。棧是程序運行時內存管理的核心區域之一,遵循后進先出原則,由操作系統或運行時環境自動分配和釋放,無需顯式干預。其設計目標是高效管理函數調用和局部變量,但受限于固定大小,需謹慎使用以避免溢出。合理的使用棧能讓程序又快又穩,濫用則容易崩潰。本篇文章到這里就結束了,感謝大家的閱讀,你們的點贊收藏加關注就是博主最大的動力。


《前期回顧》

【數據結構】——順序表鏈表(超詳細解析!!!)
C語言——結構體指南(小白一看就懂!!!)
力扣(LeetCode) ——移除鏈表元素(C語言)

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

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

相關文章

使用TexLive與VScode排版論文

前言 中文稿目前已經完成了&#xff0c;現在要轉用latex排版&#xff0c;但我對這方面沒有接觸過&#xff0c;這里做一個記錄。 網頁版Overleaf&#xff1a;Overleaf, 在線LaTeX編輯器。 TeXWorks&#xff1a;論文神器teXWorks安裝與使用記錄。 這里我還是決定采用Vscode作…

每日一題:2的冪數組中查詢范圍內的乘積;快速冪算法

題目選自2438. 二的冪數組中查詢范圍內的乘積 還是一樣的&#xff0c;先講解思路&#xff0c;然后再說代碼。 題目有一定難度&#xff0c;所以我要爭取使所有人都能看懂&#xff0c;用的方法會用最常規的思想。關于語言&#xff0c;都是互通的&#xff0c;只要你懂了一門語言…

Ceph數據副本機制詳解

Ceph 數據副本機制詳解 Ceph 的數據副本機制是其保證數據可靠性和高可用性的核心設計&#xff0c;主要通過多副本&#xff08;Replication&#xff09; 和 糾刪碼&#xff08;Erasure Coding&#xff0c;EC&#xff09; 兩種方式實現。以下是對 Ceph 數據副本機制的全面解析&am…

【八股】Mysql中小廠八股

MySQL 基礎 數據庫三大范式&#xff08;中&#xff09; 第一范式: 要求數據庫表的每一列都是不可分割的原子數據項 如詳細地址可以分割為省市區等. 第二范式: 非主鍵屬性必須完全依賴于主鍵, 不能部分依賴 第二范式要確保數據庫表中的每一列都和主鍵相關, 而不能只與主鍵的某一…

怎么使用python查看網頁源代碼

使用python查看網頁源代碼的方法&#xff1a;1、使用“import”命令導入requests包import requests2、使用該包的get()方法&#xff0c;將要查看的網頁鏈接傳遞進去&#xff0c;結果賦給變量xx requests.get(urlhttp://www.hao123.com)3、用“print (x.text)”語句把網頁的內容…

C# 多線程:并發編程的原理與實踐

深入探討 C# 多線程&#xff1a;并發編程的原理與實踐引言在現代應用開發中&#xff0c;性能和響應速度往往決定了用戶體驗的優劣。尤其在計算密集型或者IO密集型任務中&#xff0c;傳統的單線程模型可能無法有效利用多核CPU的優勢。因此&#xff0c;多線程技術成為了解決這些問…

react 常用組件庫

1. Ant Design&#xff08;螞蟻設計&#xff09;特點&#xff1a;國內最流行的企業級 UI 組件庫之一&#xff0c;基于「中后臺設計體系」&#xff0c;組件豐富&#xff08;表單、表格、彈窗、導航等&#xff09;、設計規范統一&#xff0c;支持主題定制和國際化。適用場景&…

Python 爬蟲獲取淘寶商品信息、價格及主圖的實戰指南

在電商數據分析、競品調研或商品信息采集等場景中&#xff0c;獲取淘寶商品的詳細信息&#xff08;如價格、主圖等&#xff09;是常見的需求。雖然淘寶開放平臺提供了官方的 API 接口&#xff0c;但使用這些接口需要一定的開發和配置工作。本文將通過 Python 爬蟲的方式&#x…

Ruby面向對象編程中類與方法的基礎學習例子解析

代碼示例&#xff1a; Ruby面向對象編程中類與方法的基礎學習詳細例子 1. 引言 在面向對象編程&#xff08;OOP&#xff09;中&#xff0c;類是定義對象結構和行為的藍圖。Ruby是一種純面向對象的編程語言&#xff0c;它將一切視為對象&#xff0c;包括基本數據類型。本文將…

[ Mybatis 多表關聯查詢 ] resultMap

目錄 一. resultMap 1. 使用場景: 2. 查詢映射: (1)單表查詢映射: (2)多表查詢映射: a. 在學生表里查專業 b. 在專業表里查學生 二. 其他注意事項 1. 插件下載 2. #{ } 和 ${ }的區別 一. resultMap 1. 使用場景: (1)當數據庫列名和java類中的屬性名不同時,可? r…

Rust 性能提升“最后一公里”:詳解 Profiling 瓶頸定位與優化|得物技術

一、Profiling&#xff1a;揭示性能瓶頸的“照妖鏡”在過去的一年里&#xff0c;我們團隊完成了一項壯舉&#xff1a;將近萬核的 Java 服務成功遷移到 Rust&#xff0c;并收獲了令人矚目的性能提升。我們的實踐經驗已在《RUST練習生如何在生產環境構建萬億流量》一文中與大家分…

STM32H5 的 PB14 引腳被意外拉低的問題解析 LAT1542

關鍵字&#xff1a;STM32H5&#xff0c; GPIO 1. 問題現象 客戶反饋&#xff0c;使用 STM32H523RET6 應用中配置了兩個 IO 口&#xff0c;PC9 為輸出模式&#xff0c;內部下拉&#xff1b;PB14 為輸入模式&#xff0c;內部上拉。在程序中將 PC9 引腳輸出高電平&#xff0c;結…

【辦公自動化】如何使用Python讓Word文檔處理自動化?

在日常辦公中&#xff0c;Word文檔是最常用的文本處理工具之一。通過Python自動化Word文檔操作&#xff0c;可以大幅提高工作效率&#xff0c;減少重復勞動&#xff0c;特別適合批量生成報告、合同、簡歷等標準化文檔。本文將介紹幾種常用的Python操作Word文檔的方法&#xff0…

順序表的總結及模擬實現

目錄 一.線性表 二.順序表 1.概念 2.結構 3.要實現的接口函數 三.模擬實現順序表 1.定義出順序表的基本結構 2.實現檢查擴容功能 3.實現尾插 4.實現尾刪 5.實現頭插和頭刪 6.查找 7.修改 8.遍歷 9.在指定位置插入和刪除 四.順序表的優缺點及思考 a.順序表的弊端 …

Vue3 vs Vue2:全面對比與面試寶典

文章目錄Vue3 vs Vue2&#xff1a;全面對比與面試寶典引言&#xff1a;Vue框架的進化之路一、核心架構對比二、響應式系統的革命Vue2的響應式&#xff1a;像老式監控攝像頭Vue3的響應式&#xff1a;像智能AI監控系統三、API風格的進化Vue2的Options API&#xff1a;像填表格Vue…

Java Web開發:Session與Cookie詳細入門指南

在Web開發中&#xff0c;狀態管理是核心需求之一。本文將深入講解Java中Session和Cookie的使用方法&#xff0c;幫助你掌握用戶狀態管理的核心技術。 一、Session與Cookie基礎概念 特性SessionCookie存儲位置服務器內存/持久化存儲客戶端瀏覽器安全性較高&#xff08;敏感數據…

HTTPS與CA證書:安全通信全解析

CA&#xff08;Certificate Authority&#xff09;&#xff1a;證書頒發機構&#xff0c;負責簽發和管理數字證書&#xff0c;驗證證書持有者的身份。HTTPS&#xff1a;基于 SSL/TLS 協議的 HTTP&#xff0c;通過證書實現客戶端與服務器的身份驗證和數據加密。HTTPSHTTPSSL/TLS…

AI生成代碼時代的商業模式重構:從“軟件即產品”到“價值即服務”

2025年,全球AI代碼生成市場規模突破63億元(數據來源:《中國AI代碼生成行業發展報告》),開發者效率提升40%以上,軟件開發成本下降30%。這一技術浪潮正在顛覆傳統軟件行業的商業邏輯——當代碼生成變得像文字編輯一樣簡單時,企業如何構建可持續的商業模式? 本文將從硬件…

C#特性與反射知識梳理

C#中的**特性&#xff08;Attributes&#xff09;和反射&#xff08;Reflection&#xff09;**是兩個非常重要的概念&#xff0c;它們通常用于代碼的元編程&#xff0c;允許你在運行時獲取類型信息并對其進行操作。下面對這兩個概念進行詳細梳理&#xff1a;一、C#中的特性&…

SQL 語法詳解

SQL 語法詳解 引言 SQL&#xff08;Structured Query Language&#xff09;是一種用于數據庫管理的標準語言&#xff0c;它允許用戶進行數據的查詢、更新、插入和刪除等操作。SQL語法是數據庫管理和編程的基礎&#xff0c;本篇文章將詳細介紹SQL的基本語法和常用操作&#xff0…