> 文档中心 > 数据结构04 - 手把手带你拿捏操作受限的线性表 - 栈(附带超详细的用C语言模拟实现栈)

数据结构04 - 手把手带你拿捏操作受限的线性表 - 栈(附带超详细的用C语言模拟实现栈)


数据结构与算法

Lesson04 - 操作受限的线性表 - 栈


文章目录

  • 数据结构与算法
  • 前言
    • 1.1 栈基本概念
    • 1.2 栈的实现
      • 1.2.1 栈的创建(Stack st)
      • 1.2.2 初始化(Init)
      • 1.2.3 进栈(入栈 - Push)
      • 1.2.4 出栈(Pop)
      • 1.2.5 获得栈顶元素(StackTop)
      • 1.2.6 检查栈是非为空(IsStackEmpty)
      • 1.2.7 销毁栈(StackDestroy)
  • //后记

前言

💘 Lesson04 主要讲解数据结构中两个操作受限的线性表 - 栈和队列
💘 重点讲解栈和队列的基本概念和特点
💘 然后用C语言模拟实现栈和队列
💘 本篇文章没有伪代码,帮助大家在理解的前提下,自己动手用C语言实现栈和队列

1.1 栈基本概念

🏃 回顾一下我们之前学习过的线性表,我们可以在表中任意位置插入和删除元素
🏃 如果插入和删除操作只允许在一端进行的话,那么我们赋予线性表一个特殊的名字 - 栈(Stack)
🏃 :只允许在一端进行插入和删除操作的线性表

🏃 其中进行插入和删除操作的一端称为 - 栈顶(Top)
🏃 另一端称为 - 栈底(Bottom)
🏃 栈的插入操作称为 - 进栈(Push)
🏃 栈的删除操作称为 - 出栈(Pop)

💘 结构图如下:
在这里插入图片描述

🏃 由上图可以看出,后进去的元素,出去的时候最先出去
🏃 以此,栈有一个特性,也是原则 - 后进先出 LIFO(Last In First Out)

1.2 栈的实现

🏃 结合我们在线性表学到的知识:线性表的实现可以用顺序表(数组)或者链表
🏃 以此我们来讨论一下,栈的实现选择顺序表还是链表

🏃 由栈的结构可知,我们对栈的操作大多都是在栈顶实现的。
🏃 如果用链表,我们需要频繁找到链表的尾部节点,比较费劲
🏃 而顺序表可以通过表中有效元素个数,轻易的访问到最后一个元素

💘 以此,我们可以选择数组来实现栈

1.2.1 栈的创建(Stack st)

💘 我们可以用定长的静态数组创建栈,也可以用动态增长的数组创建栈
在这里插入图片描述

💘 静态栈的创建

typedef int STDataType;//静态栈#define MAX_SIZE 10typedef struct Stack{STDataType a[MAX_SIZE];//定长的数组来存栈的元素int top;//用来记录栈顶的位置,可以记录元素的个数}Stack;int main(){Stack st;return 0;}

💘 动态栈的创建

typedef int STDataType;//动态栈typedef struct Stack{STDataType* a;//可以用malloc申请可以动态增长的数组int top;//记录栈顶元素的位置int capacity;//记录最大容量,方便扩容}Stack;int main(){Stack st;return 0;}

1.2.2 初始化(Init)

🏃 动态申请一个数组,修改栈里面的参数

//初始化 - 默认容量是10void StackInit(Stack* st)//由于修改里面的参数,以此需要传地址{//默认容量是10st->capacity = 10;int* tmp = (int*)malloc(sizeof(int) * st->capacity);if (tmp == NULL){perror("StackInit::malloc");}st->a = tmp;st->top = 0;//没有元素时,top指向0位置}

1.2.3 进栈(入栈 - Push)

🏃 进栈元素插入 top 所指的位置,然后将 top的值 +1

在这里插入图片描述

🏃 但是如果,top == capacity,说明不能再插入元素了,需要增容
🏃 因此我们第一步先判断是否已满

//进栈void StackPush(Stack* st, STDataType x){//进栈第一步先判断是否已满if (st->top == st->capacity){STDataType* tmp = (int*)realloc(st->a, sizeof(int) * st->capacity * 2);if (tmp == NULL){perror("StackPush::realloc");}st->a = tmp;st->capacity *= 2;//增容后一定要更改最新容量}//进栈操作仅需一步st->a[st->top++] = x;}

1.2.4 出栈(Pop)

🏃 只需将 top 的值 -1 即可在逻辑上删除元素

在这里插入图片描述

🏃 但是需要注意一点,如果栈为空,则不能出栈

//出栈void StackPop(Stack* st){if (st->top == 0)return;elsest->top--;}

1.2.5 获得栈顶元素(StackTop)

🏃 栈顶元素就是 top 所指位置的前一个

ps: 由于很简单,这里就不给图咯

//获取栈顶元素STDataType StackTop(const Stack* st){return st->a[st->top - 1];}

1.2.6 检查栈是非为空(IsStackEmpty)

🏃 如果栈的 top 值为0,则栈为空

//判空bool IsStackEmpty(Stack* st){return st->top == 0;//如果为空,判断为真,返回true,否则返回false}

1.2.7 销毁栈(StackDestroy)

🏃 清空栈内数据

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

💘 以上就是栈的重点内容,其实在我们学完线性表后,只要注意好细节,栈的自主实现已经不成问题

//后记

🏃 以后每周会更新一到两篇学习数据结构的笔记,用来记录自己的学习历程,复习巩固所学的知识。
🏃 文中概念或者代码有任何错误的地方,希望大佬们在评论区指出,本人会虚心接受并且改正。