当前位置: 首页 > news >正文

栈:“后进先出” 的艺术,撑起程序世界的底层骨架

前言:

        厨房里叠放的盘子想必大家都见过,新洗好的只能放在最顶层,使用时也必须从最上层开始取。羽毛球桶里的羽毛球也是如此,用过的球只能放回顶层,取用时也必须从最上层拿取。这些日常场景里,其实都藏着一种重要的数据结构:栈。

本文系统讲解栈这一数据结构,从基础概念到实际应用进行全面剖析。通过清晰的逻辑和丰富的实例,即使是数据结构初学者也能轻松掌握核心要点。

一、栈的基本概念

        

1.1栈的定义

        栈  (stack) 是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作,其核心特性遵循后进先出原则,这种特性可以形象地类比为叠放盘子的过程:最晚放入的盘子  (后进)  会被最先取出  (先出)  ,而最早放入的盘子  (先进)  则最后才能取出  (后出)  。

                

1.2栈的基础知识     

        为了方便理解,我们先明确栈的 3 个核心概念:​

栈顶(Top):位于栈的最上层,即最后入栈的元素。所有入栈(push)和出栈(pop)操作都只能在栈顶进行。

        

栈底(Bottom):位于栈的最底层,即第一个入栈的元素。这个元素在栈中位置固定,不会轻易变动。

        

空栈(empty):没有任何元素的栈状态。此时无法执行出栈操作。

        

1.3进栈出栈的示意图

        

进栈(Push):将元素添加到栈顶

出栈(Pop):移除并返回栈顶元素

        

二、栈的实现

        

2.1栈实现的相关接口

      本文通过数组的方式实现栈 ,实现的相关接口如图所示:

        

2.2栈实现的相关文件

                    

2.3Stack.h文件

        Stack.h头文件实现:通过结构体定义栈,声明栈的相关接口函数。

#pragma once
#include<stdlib.h>
#include<stdio.h>
#include<stdbool.h>
#include<assert.h>
typedef int STDatatype;typedef struct Stack
{STDatatype* a;//top表示指向栈顶元素的下一个元素下标int top;//栈的容量大小int capacity;
}Stack;//初始化和销毁栈
void StackInit(Stack* pst);void StackDestroy(Stack* pst);//元素的入栈和出栈void Push(Stack* pst,STDatatype x);void Pop(Stack* pst);//获取栈顶元素
STDatatype top(Stack* pst);//获取栈中有效元素个数 
int Size(Stack* pst);//判断栈是否为空
bool Empty(Stack* pst);

        

对于Stack.h头文件主要关注:

typedef int STDatatype;typedef struct Stack
{STDatatype* a;//top表示指向栈顶元素的下一个元素下标int top;//栈的容量大小int capacity;
}Stack;

typedef int STDatatype;

        
把 int 重命名为 STDatatype,方便后续修改栈存储的元素类型(比如想存 char 或结构体,只需改这一行)。

        
struct Stack

        

结构体:定义栈的核心结构。

        
STDatatype* a; 

        

动态数组指针,指向栈的内存空间(存储栈的元素)。

        
int top; 

        

栈顶标记(注释说明 “指向栈顶元素的下一个元素下标”)。例如:栈空时 top=0;入栈一个元素后,top=1(此时栈顶元素是 a[0])

        
int capacity;

        

栈的容量(当前分配的内存能存多少个元素),用于判断是否需要扩容。        

        

2.4Stack.c文件

①栈的初始化

void StackInit(Stack* pst)
{//断言pstassert(pst);pst->a = NULL;pst->capacity = 0;//指向栈顶元素的下一个元素pst->top = 0;
}

        

②栈的销毁

//销毁栈
void StackDestroy(Stack* pst)
{assert(pst);if (pst->a != NULL){free(pst->a);pst->a = NULL;}pst->capacity = 0;pst->top = 0;
}

        

③入栈

//元素的入栈
void Push(Stack* pst, STDatatype x)
{assert(pst);//判断是否容量足够if (pst->capacity == pst->top){//需要进行扩容int newcapacity =pst->capacity==0? 4 : pst->capacity * 2;STDatatype* tmp = (STDatatype *)realloc(pst->a, newcapacity*sizeof(STDatatype));if (tmp == NULL){perror("realloc fail");return;}pst->a = tmp;pst->capacity = newcapacity;}//进行入栈pst->a[pst->top++] = x;}

         

④出栈

//元素的出栈
void Pop(Stack* pst)
{assert(pst && pst->top > 0);pst->top--;
}

      

⑤获取栈顶元素

//获取栈顶元素
STDatatype top(Stack* pst)
{assert(pst && pst->top > 0);return pst->a[pst->top-1];
}

        

⑥获取栈中的有效个数

//获取栈中有效元素个数 
int Size(Stack* pst)
{assert(pst);return pst->top;
}

      

⑦判断栈是否为空

//判断栈是否为空
bool Empty(Stack* pst)
{assert(pst);return pst->top == 0;
}

        

2.5Test.c文件

#include"Stack.h"void Test()
{Stack st = { 0 };StackInit(&st);Push(&st, 1);printf("%d\n", top(&st));Push(&st, 2);printf("%d\n", top(&st));Push(&st, 3);printf("%d\n", top(&st));Push(&st, 4);printf("%d\n", top(&st));printf("当前栈中元素的总个数为:%d\n", Size(&st));Pop(&st);printf("%d\n", top(&st));Pop(&st);printf("%d\n", top(&st));Pop(&st);printf("%d\n", top(&st));Pop(&st);if (Empty(&st))printf("当前栈为空\n");elseprintf("当前栈不为空\n");printf("当前栈中元素的总个数为:%d\n", Size(&st));StackDestroy(&st);
}int main()
{Test();return 0;
}

        

三、栈的简单应用

        

Leetcode链接:有效的括号  

        

3.1题目简介:

        

3.2题目分析

        

当开始接触题目时,我们会不禁想到如果计算出左括号的数量,和右括号的数量,如果每种括号左右数量相同,会不会就是有效的括号了呢?

        

但是左括号和右括号是否匹配还和它的位置相关,例如 " ]][[ " 这样一组案例即使左右括号数量相同,但是位置不满足题目条件。

        

我们通过仔细分析这样一组测试样例:{ ( ) [ ( ) ] }  ,对于有效的括号,它的部分子表达式仍然是有效的括号。

        

故而可以使用栈来解决,对于左括号压入栈中,通过匹配右括号的方式,删除最小的括号对。

        

       

        

3.3代码示例

class Solution {
public:bool isValid(string s) {//创建一个栈结构stack<char> st;for(int i=0;i<s.length();i++){//如果是左括号( { [ 进入栈中if(s[i]=='('|| s[i]=='{' || s[i]=='['){st.push(s[i]);}else //右括号{//取出左括号的前提是栈中至少有左括号if(st.empty()){return false;}//取出栈顶元素char ch=st.top();st.pop();//栈顶元素的左括号 与 右括号进行匹配 if( (ch=='('&&s[i]!=')') || (ch=='{'&&s[i] !='}') || (ch=='['&&s[i] !=']') ) {return false;}}}//如果遍历完字符串,栈中还有元素,说明左右括号数量不匹配if(!st.empty()) return false; return true;}
};

        

既然看到这里了,不妨点赞+收藏,感谢大家,若有问题请指正。

http://www.dtcms.com/a/454088.html

相关文章:

  • JAVA算法练习题day32
  • 网站添加设置着陆页唐山网站优化
  • 做婚纱网站的目的seo的主要工作是什么
  • 上海哪家做网站校园无线网络设计方案
  • 深入解析Doris ZoneMap索引机制
  • (1)SwiftUI基础入门教程
  • wordpress整站搬家教程河池做网站
  • 怎么改版一个网站白酒网站设计
  • windows显示驱动开发-节能与 VSync 控制
  • 安徽省住房和城乡建设厅官方网站网站访问量大
  • 好的平面设计网站有哪些易云巢做营销型网站
  • 从0死磕全栈之Next.js 中的错误处理机制详解(App Router)
  • c语言贪吃蛇游戏开发
  • 360网站seo优化怎么做简单网站
  • 小说网站静态模板设计师设计费一般多少
  • 网站主机要怎么做跨境电商交3980元培训费可信吗
  • Coze源码分析-资源库-编辑知识库-后端源码-流程/技术/总结
  • 哺乳动物双等位基因表达的 “守护者”--解析 MSL2对基因剂量平衡与疾病机制的新启示--文献精读164
  • 阿里云网站建设需要多少钱开发软件公司都有哪些
  • CTFHub SQL注入通关笔记4:布尔盲注(手注法+脚本法)
  • 虎书Fundamentals Of Computer Graphics翻译及笔记(1)——前言
  • 建网站公司室内设计效果图网站推荐
  • 网站建设收徒弟设计韩国电影完整版下载
  • 应聘网站优化的简历怎么做全新升级网站
  • 我的第一个网站
  • windows下将redis注册为windows服务
  • IT架构中的前后中台:SuperCell与阿里中台战略启示
  • 外贸工厂的网站建设长沙做网站智投未来
  • 国外商品网站企业微网站建站
  • 第六章 面向对象编程(基础部分)