【数据结构】栈(Stack)的实现 -- 详解

news/2025/3/15 18:49:01/

一、栈的概念及结构

1、概念

:一种特殊的线性表,其只允许在表尾进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出 LIFO(Last In First Out)的原则。


压栈:栈的插入操作叫做进栈 / 压栈 / 入栈,入数据在栈顶

出栈:栈的删除操作叫做出栈。出数据也在栈顶


2、结构 

 


二、栈的实现

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为栈只会在一端进行插入和删除操作,用数组效率还是比较高,数组在尾上插入数据的代价比较小。当然,也会存在一些问题,就是每次空间不够,要重新开辟空间,可能会造成一些内存浪费。

1、栈的顺序存储结构

数组的首元素作为栈底,另外一端作为栈顶,同时定义一个变量 top 来记录栈顶元素在数组中的位置。 


2、栈的链表存储结构 

单链表的尾部作为栈底,头部作为栈顶,方便插入和删除(进栈头插,出栈头删),头指针和栈顶指针 top 合二为一。


三、栈的实现

1、创建文件

  • test.c(主函数、测试栈各个接口功能)
  • Stack.c(栈接口函数的实现)
  • Stack.h(栈的类型定义、接口函数声明、引用的头文件)

2、Stack.h 头文件代码

下面是动态增长的栈的结构,在实际中更常用。

#pragma once
#include <stdio.h>
#include <assert.h> // assert
#include <stdlib.h> // realloc
#include <stdbool.h> // bool// 支持动态增长的栈
typedef int STDataType; // 类型重命名 栈中元素类型先假设为inttypedef struct Stack
{STDataType* a; // 指向动态开辟的数组int top; // 记录栈顶位置int capacity; // 栈的容量大小
}Stack;// 初始化栈
void StackInit(Stack* ps); 
// 销毁栈
void StackDestroy(Stack* ps);
// 入栈
void StackPush(Stack* ps, STDataType data); 
// 出栈
void StackPop(Stack* ps); 
// 获取栈顶元素
STDataType StackTop(Stack* ps); 
// 获取栈中有效元素个数
int StackSize(Stack* ps); 
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps); 

四、Stack.c 中各个接口函数的实现

1、栈的初始化

// 初始化栈
void StackInit(Stack* ps)
{assert(ps);ps->a = NULL;//思路一:ps->top = 0; // 意味着top指向栈顶数据的下一个//思路二://ps->top = -1; // 意味着top指向栈顶数据ps->capacity = 0;
}

思路二: 

 


2、栈的销毁

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

3、入栈

// 入栈
void StackPush(Stack* ps, STDataType x)
{assert(ps);if (ps->top == ps->capacity) // 检查栈空间是否满了{int newCapacity = (ps->capacity == 0) ? 4 : (ps->capacity) * 2;STDataType* tmp = realloc(ps->a, sizeof(STDataType) * newCapacity); // 扩容至新容量if (tmp == NULL){printf("realloc fail\n");exit(-1);}ps->a = tmp;ps->capacity = newCapacity; // 更新容量}ps->a[ps->top] = x; // 将新增元素放入栈顶空间ps->top++; // 栈顶指针加一
}

4、出栈

// 出栈
void StackPop(Stack* ps)
{assert(ps);assert(!StackEmpty(ps)); // 栈不能为空ps->top--; // 栈顶指针减一
}

5、获取栈顶元素

// 获取栈顶元素
STDataType StackTop(Stack* ps)
{assert(ps);assert(!StackEmpty(ps)); // 栈不能为空return ps->a[ps->top-1];
}

6、获取栈中有效元素个数

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

7、检测栈是否为空

// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
bool StackEmpty(Stack* ps)
{assert(ps);//写法一:/*if (ps->top == 0){return true;}else{return false;}*///写法二:return ps->top == 0;
}

五、代码整合

// Stack.c
#include "Stack.h"// 初始化栈
void StackInit(Stack* ps)
{assert(ps);ps->a = NULL;ps->top = 0; // 意味着top指向栈顶数据的下一个ps->capacity = 0;
}// 销毁栈
void StackDestroy(Stack* ps)
{assert(ps);if (ps->a){free(ps->a);}ps->a = NULL;ps->top = 0;ps->capacity = 0;
}// 入栈
void StackPush(Stack* ps, STDataType x)
{assert(ps);if (ps->top == ps->capacity) // 检查栈空间是否满了{int newCapacity = (ps->capacity == 0) ? 4 : (ps->capacity) * 2;STDataType* tmp = realloc(ps->a, sizeof(STDataType) * newCapacity); //扩容至新容量if (tmp == NULL){printf("realloc fail\n");exit(-1);}ps->a = tmp;ps->capacity = newCapacity; // 更新容量}ps->a[ps->top] = x; // 将新增元素放入栈顶空间ps->top++; // 栈顶指针加一
}// 出栈
void StackPop(Stack* ps)
{assert(ps);assert(!StackEmpty(ps)); // 栈不能为空ps->top--; // 栈顶指针减一
}// 获取栈顶元素
STDataType StackTop(Stack* ps)
{assert(ps);assert(!StackEmpty(ps)); // 栈不能为空return ps->a[ps->top-1];
}// 获取栈中有效元素个数
int StackSize(Stack* ps)
{assert(ps);return ps->top;
}// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
bool StackEmpty(Stack* ps)
{assert(ps);return ps->top == 0;
}

六、测试栈的功能

栈的实现不能像顺序表一样,去实现一个打印函数来遍历栈并输出,这样做就不符合栈的特点了(只能在栈顶插入删除,后进先出),所以我们这样来实现出栈:获取并打印栈顶元素,再删除栈顶元素,继续获取新的栈顶元素。


http://www.ppmy.cn/news/991306.html

相关文章

vue项目环境 搭建

1、安装nodejs 2、安装vue-cli, npm i -g vue/cli-init 3、初始化项目 vue init webpack test 4、运行 cd test npm run dev

windows下配置vue开发环境

安装nodejs&#xff0c;配置npm 1.下载安装包&#xff1a;下载地址&#xff1a;https://nodejs.org/en/download 2.安装node&#xff1a;下载完成后进行安装&#xff0c;记住安装的文件夹。本人安装路径为 D:\Program Files\nodejs 3.配置环境变量&#xff1a; ①安装完成后…

忘掉MacType吧,TtfAutoHint手工删除ttc、ttf字体的hinting

Windows的ClearType渲染字体方式&#xff0c;结合臭名昭著的hinting技术使微软雅黑字体备受争议&#xff0c;正所谓&#xff1a;成也hinting&#xff0c;败也hinting。 首先什么是hinting&#xff1f; Hinting 这个词一直都没有中文名称&#xff0c;我用粤语将它音译为“牵挺”…

点击图片1.全屏阅览2.下载3.关闭 纯纯html css js

要实现图片点击全屏预览的功能&#xff0c;可以使用JavaScript和CSS来实现。以下是一个简单的示例代码&#xff1a; html <!DOCTYPE html> <html> <head><meta charsett"UTF-8"><title>图片点击全屏预览</title><style>…

SQL注入漏洞及解决(PreparedStatement对象)

四、SQL注入漏洞 加个or true都能查出来&#xff0c;很危险&#xff01;&#xff01;&#xff01; 会报错&#xff0c;因为代码中也拼了个引号 我们使用#将后面的内容注释起来&#xff0c;前面还是条完整的sql&#xff0c;还是能查到 使用—注释&#xff0c;代码可能加trim()&…

最小时间差(力扣)排序 + 思维 JAVA

给定一个 24 小时制&#xff08;小时:分钟 “HH:MM”&#xff09;的时间列表&#xff0c;找出列表中任意两个时间的最小时间差并以分钟数表示。 示例 1&#xff1a; 输入&#xff1a;timePoints [“23:59”,“00:00”] 输出&#xff1a;1 示例 2&#xff1a; 输入&#xff1a;…

题解:ABC275D - Yet Another Recursive Function

题解&#xff1a;ABC275D - Yet Another Recursive Function 题目 链接&#xff1a;Atcoder。 链接&#xff1a;洛谷。 难度 算法难度&#xff1a;普及。 思维难度&#xff1a;入门。 调码难度&#xff1a;入门。 综合评价&#xff1a;简单。 算法 记忆化深度优先搜索…

基于FPGA的VGG16卷积神经网络加速器--WL

VGG16是一个典型的卷积神经网络&#xff0c;由13层卷积层&#xff0c;5层池化层和3层全连接层组成。且卷积层的计算时间在整个计算过程中占比极大&#xff0c;通过FPGA的并行运算可以有效的加快卷积层的计算速度。 一个卷积层可以有若干个卷积核&#xff0c;以第一层为例&#…