数据结构------栈的介绍和实现

news2024/11/23 16:53:09

目录

1.栈的一些初步认识

2.栈的实现

3.相关的函数介绍

(1)栈的初始化

(2)栈的销毁

(3)栈的数据插入 

(6)判断是否为空

(7)栈的大小

4.栈的实现完整代码

(1)stack.h

(2)stack.c

(3)test.c

5.栈的应用--有效的括号


1.栈的一些初步认识

相信前面看过我的函数栈帧的创建和销毁这篇博客的小伙伴们对于栈已经有了一个初步的了解

因为在那个博客里面,我们提到了栈顶指针,栈底指针,压栈,出栈等等一些专业术语;

现在我们来系统的认识一下栈:

栈实际上也是一个存储数据的结构,和我们的线性表是一样的,但是栈肯定是有自己的独特之处的,否则也不会作为一个单独的数据结构存在,确实,栈的特殊性就在于我们的数据都是从栈顶进入,栈顶出去,这个就是栈的特殊之处;

栈的这个特性使得先进去的数据后出来,后进栈的数据先出来,这个有什么好处呢?我们现在可能还体会不到,我通过一个例子大家就可以体会到栈的用途,栈是有用的;

比如我们想要判断一串符号的顺序:看看是不是一一对应的,例如{(【】)}这个肯定就是一一对应的符号组合,但是对于{【(}】)这个就不是一一对应的符号,我们是用肉眼可以看出来的,但是如果有题目让我们设计程序进行判断呢?

拿这个{(【】)}作为案例,我们的{先进栈,(再进栈,【再进栈,这个时候我们的左边的括号都判断完了,我们需要判断右边的符号和左边的是不是一一对应的,这个时候就可以使用栈这个数据结构,因为我们的栈是后进先出,前面的3个符号进栈之后,我们就可以让他们依次出栈和我们后面的几个符号进行比较,例如这里的大括号第一个进栈,小括号第二个进栈,中括号第三个进栈,我们要向看看是否匹配,就只需要判断第四个的符号中括号和我们第一个出栈的符号是否匹配,这个时候栈这个数据结构就可以帮助我们判断这个一串符号前后是不是一一对应的。

2.栈的实现

我们还是写一个系统的文件,包括栈的实现的头文件,源文件和测试文件这三个文件;

我们在头文件里面进行相关函数的声明,源文件里面进行相关的函数的定义,测试文件里面定义一个栈进行我们写的函数的测试;

我们这里是定义了一些函数:栈的初始化,栈的销毁,栈里面插入数据,栈里面删除数据,返回栈顶的数据,判断栈是否是空的,栈的大小;

3.相关的函数介绍

(1)栈的初始化

这里就是把数组置空,栈顶的位置设为0,容量设置为0,这里是top指的是栈顶的位置,我们这里初始化为0,实际上指的是栈顶的下一个元素,实际情况下,栈这个时候是空的,我们应该初始化为-1,我们初始化为0方便后面的插入数据,我们插入数据就是在栈顶的下一个位置进行插入的,因此我们初始化为0可以方便后续的数据的插入;

(2)栈的销毁

就是释放掉数组的空间,栈顶位置和栈的容量都设置为0就可以了;

(3)栈的数据插入 

我们要为这个栈开辟空间,把我们要插入的数据给插入进去,再让栈顶的位置加加就行了;

(4)栈的元素删除 

这个就是不断的删除栈顶的元素,让栈顶位置元素不断的弹出,最后不断的让top--,但是这个栈的元素的个数是有限的,肯定不能一直进行top--把,我们调用这个判断是否为空的函数进行断言,因为这个函数判断的是为空的,所以我们断言的时候取非,这个时候过了再进行top--;

(5)取出栈的元素

返回值就是我们取出来的元素,还是要进行断言,因为栈里面的元素个数是有限的,我们肯定不能一直取出元素;

(6)判断是否为空

我们设置布尔值,pst->top为0时候,说明栈里面没有元素,是空的,我们就返回true,否则就返回false;

(7)栈的大小

我们还是返回pst->top表示的是栈顶的下一个位置,下表和个数是相差1的,如果是2个元素,我们的pst->top表示的是栈顶的下一个元素位置,下标是从0开始的,栈顶的下一个元素就是第三个元素,下标就是2,我们返回的就是2个元素的个数; 

4.栈的实现完整代码

(1)stack.h

#pragma once
#include<stdbool.h>
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int sldatatype;
typedef struct stack
{
	sldatatype* a;
	int top;
	int capacity;
}stack;

void stackinit(stack* pst);

void stackdestory(stack* pst);

void stackpush(stack* pst, sldatatype x);

void stackpop(stack* pst);

sldatatype stacktop(stack* pst);

bool stackempty(stack* pst);

int size(stack* pst);

(2)stack.c

#include"stack.h"

void stackinit(stack* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->top = 0;//指向栈顶的下一个元素
	pst->capacity = 0;
}

void stackdestory(stack* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->top = 0;
	pst->capacity = 0;
}

void stackpush(stack* pst, sldatatype x)
{
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : (pst->capacity * 2);
		sldatatype* temp = (sldatatype*)realloc(pst->a, newcapacity * sizeof(sldatatype));
		if (temp == NULL)
		{
			perror("realloc fail!");
			return;
		}
		pst->a = temp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}

void stackpop(stack* pst)
{
	assert(pst);
	assert(!stackempty(pst));
	pst->top--;
}

sldatatype stacktop(stack* pst)
{
	assert(pst);
	assert(!stackempty(pst));
	return pst->a[pst->top - 1];
}

bool stackempty(stack* pst)
{
	assert(pst);
	return pst->top == 0;
}

int size(stack* pst)
{
	assert(pst);
	return pst->top;
}

(3)test.c

#include"stack.h"

void test1()
{
	stack s1;
	stackinit(&s1);
	stackpush(&s1, 1);
	stackpush(&s1, 2);
	stackpush(&s1, 3);
	stackpush(&s1, 4);
	while (!stackempty(&s1))
	{
		printf("%d ", stacktop(&s1));
		stackpop(&s1);
	}
	stackdestory(&s1);
}
int main()
{
	test1();
	return 0;
}

我们这里进行栈里面的数据打印的时候是设置了一个循环,我们每打印一个数据,就弹出栈顶位置的元素,这个时候就有一个新的数据成为栈顶,我们再打印新的栈顶位置数据 。

5.栈的应用--有效的括号

这里的应用就是我们开始提到的括号的匹配问题,我们要判断这个括号之间是否是相互匹配的;

因为现阶段我们还是使用C语言进行实现,所以我们要自己实现栈,如果是C++,我们可以使用相应的一些库,我们可以直接进行调用,这里我们就把上面实现的函数复制过来就可以了。

代码展示:

#include<stdbool.h>
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef char sldatatype;
typedef struct stack
{
	sldatatype* a;
	int top;
	int capacity;
}stack;

void stackinit(stack* pst);

void stackdestory(stack* pst);

void stackpush(stack* pst, sldatatype x);

void stackpop(stack* pst);

sldatatype stacktop(stack* pst);

bool stackempty(stack* pst);

int size(stack* pst);

void stackinit(stack* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->top = 0;//指向栈顶的下一个元素
	pst->capacity = 0;
}

void stackdestory(stack* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->top = 0;
	pst->capacity = 0;
}

void stackpush(stack* pst, sldatatype x)
{
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : (pst->capacity * 2);
		sldatatype* temp = (sldatatype*)realloc(pst->a, newcapacity * sizeof(sldatatype));
		if (temp == NULL)
		{
			perror("realloc fail!");
			return;
		}
		pst->a = temp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}

void stackpop(stack* pst)
{
	assert(pst);
	assert(!stackempty(pst));
	pst->top--;
}

sldatatype stacktop(stack* pst)
{
	assert(pst);
	assert(!stackempty(pst));
	return pst->a[pst->top - 1];
}

bool stackempty(stack* pst)
{
	assert(pst);
	return pst->top == 0;
}

int size(stack* pst)
{
	assert(pst);
	return pst->top;
}
bool isValid(char* s) 
{
    stack s1;
    stackinit(&s1);
    while(*s)
    {
        if(*s=='('||*s=='['||*s=='{')
        {
            stackpush(&s1,*s);
        }
        else
        {
            if(stackempty(&s1))
            {
                stackdestory(&s1);
                return false;
            }
            char top=stacktop(&s1);
            stackpop(&s1);
            if(*s==']'&&top!='['||*s=='}'&&top!='{'||*s==')'&&top!='(')
            {
                stackdestory(&s1);
                return false;
            }
            else
            {

            }
        }
        ++s;
    }
    bool ret=stackempty(&s1);
    stackdestory(&s1);


    return ret;
}

(1)这个代码看上去比较复杂,实际上前面的很多都是在自己实现一个栈,只有inValid才是真正的一个接口函数,其他的都是为这个函数服务的,我们的inValid函数调用其他的函数进行相应的判断;

(2)因为我们这里是对符号进行判断,所以我们的头文件里面的int需要修改为char类型数据,这个时候我们的typedef int sldatatype的作用就显示了出来。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1640930.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【全网首出】npm run serve报错 Expression: thread_id_key != 0x7777

总结 困扰了一天&#xff01;&#xff01;&#xff01;一直以为是自己哪里配置错了&#xff0c; 结果最后发现是node.js官方的问题&#xff0c; Node.js v16.x版本的fibers.node被弃用 本文阅读大概&#xff1a;3min #npm run serve时就报错 #找了一天的文章&#xff0c;找不…

【前端学习——call和apply函数】

call()和apply()这两个方法的作用可以简单归纳为改变this指向&#xff0c;从而让我们的this指向不在是谁调用了函数就指向谁。 call()方法的作用和 apply() 方法类似&#xff0c;区别就是call()方法接受的是参数列表&#xff0c;而apply()方法接受的是一个参数数组。 https:/…

HTML_CSS学习:常用文本属性

一、文本颜色 相关代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>文本颜色</title><style>div{font-size: 90px;}.atguigu1{color: #238c20;}.atguigu2{color: rgb(2…

【数据结构(邓俊辉)学习笔记】向量06——位图

文章目录 0.概述1.结构2.实现3. 应用3.1 去重3.2 筛法 0.概述 位图&#xff08;Bitmap&#xff09;是一种特殊的序列结构&#xff0c;可用以动态地表示由一组&#xff08;无符号&#xff09;整数构成的集合。 test() 判断k 是否存在集合S中。set() 将k 加入到集合S中。clear…

视频编辑软件pitivi基本功之将三个相关视频合并成一个视频

视频编辑软件pitivi基本功之将三个相关视频合并成一个视频 一、素材来源&#xff1a;网站下载 到http://cpc.people.com.cn/GB/67481/435238/437822/437828/437900/index.html下载以下三个视频&#xff0c;鼠标右击视频——另存视频为 庆祝中国共产党成立100周年大会即将开始—…

深度学习:基于TensorFlow、Keras,使用长短期记忆神经网络模型(LSTM)对Microsoft股票进行预测分析

前言 系列专栏&#xff1a;机器学习&#xff1a;高级应用与实践【项目实战100】【2024】✨︎ 在本专栏中不仅包含一些适合初学者的最新机器学习项目&#xff0c;每个项目都处理一组不同的问题&#xff0c;包括监督和无监督学习、分类、回归和聚类&#xff0c;而且涉及创建深度学…

R语言数据探索和分析7-使用随机森林模型对中国GDP及其影响因素分析

一、研究背景和意义 国内生产总值&#xff08;GDP&#xff09;是宏观经济领域中最为关注的经济统计数据之一&#xff0c;它反映了一个国家或地区在一定时期内所创造的所有最终商品和服务的总价值。GDP的增长率不仅仅是一个国家经济健康状况的关键指标&#xff0c;还直接关系到…

Web前端一套全部清晰 ⑥ day4 CSS.1 基础选择器、文字控制属性

后来的我不在抱怨 所有的事与愿违都是我能力或者判断力不足 仅此而已 —— 24.5.1 一、CSS定义 1. 将CSS放在html文件的<style>标签中 层叠样式表(Cascading style Sheets&#xff0c;缩写为 CSS)&#xff0c;是一种 样式表 语言&#xff0c;用来描述 HTML 文档的呈现(美…

软件应用开发安全设计指南

1.1 应用系统架构安全设计要求 设计时要充分考虑到系统架构的稳固性、可维护性和可扩展性&#xff0c;以确保系统在面对各种安全威胁时能够稳定运行。 在设计系统架构时&#xff0c;要充分考虑各种安全威胁&#xff0c;如DDoS攻击、SQL注入、跨站脚本攻击&#xff08;XSS&…

Github 2024-05-03 Java开源项目日报 Top9

根据Github Trendings的统计,今日(2024-05-03统计)共有9个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Java项目9Kotlin项目1C++项目1libGDX: 跨平台Java游戏开发框架 创建周期:4284 天开发语言:Java, C++协议类型:Apache License 2.0Star数量:2…

如何在Android设备上恢复丢失的照片

Android手机或平板电脑上的照片丢失了&#xff1f;不要惊慌&#xff0c;您也许可以恢复它们。 由于我们的大量数据和日常生活都存储在一台设备上&#xff0c;有时将所有照片存储在本地的 Android 智能手机或平板电脑上可能是一项冒险的工作。无论是通过事故&#xff08;损坏、…

【JVM】从硬件层面和应用层面的有序性和可见性,到Java的volatile和synchronized

Java的关键字volatile保证了有序性和可见性&#xff0c;这里我试着从底层开始讲一下有序性和可见性。 一&#xff0c;一致性 数据如果同时被两个cpu读取了&#xff0c;如何保证数据的一致性&#xff1f;或者换句话说&#xff0c;cpu1改了数据&#xff0c;cpu2的数据就成了无效…

【C++】深入剖析C++11 initializer_list 新的类功能 可变模板参数

目录 一、std::initializer_list 1、std::initializer_list是什么类型 2、std::initializer_list 的应用场景 ①给自定义容器赋值 ② 传递同类型的数据集合 二、新的类功能 1、默认成员函数 2、关键字default 3、关键字delete 三、可变参数模板 一、std::initialize…

C++仿函数周边及包装器

我最近开了几个专栏&#xff0c;诚信互三&#xff01; > |||《算法专栏》&#xff1a;&#xff1a;刷题教程来自网站《代码随想录》。||| > |||《C专栏》&#xff1a;&#xff1a;记录我学习C的经历&#xff0c;看完你一定会有收获。||| > |||《Linux专栏》&#xff1…

RunnerGo四月更新:强化UI自动化测试与UI录制插件功能

RunnerGo最近更新的 UI自动化测试和UI录制插件可以让测试人员更高效地布置UI自动化场景。这次优化升级的插件录制能力&#xff0c;可以更准确的定位元素并执行步骤&#xff0c;并增加了局部截图功能&#xff0c;准确查看定位的元素位置等。 UI插件V2.0介绍 接下来&#xff0c;让…

python基础算法题0502

数字反转 无论是字符串反转还是数字反转&#xff0c;其实都一样。 需求 代码 class Solution:def reverse(self, x: int) -> int:if 0 < x < 2 ** 31 - 1:m str(x)[::-1]if int(m)<2**31-1:return int(m)else:return 0if 0 > x > -2 ** 31:y -xn str(y…

2.6Java全栈开发前端+后端(全栈工程师进阶之路)-前端框架VUE3-基础-Vue生命周期

在使用vue进行日常开发中&#xff0c;我们总有这样的需求&#xff0c;想在页面刚一加载出这个表格组件时&#xff0c;就发送请求去后台拉取 数据&#xff0c;亦或者想在组件加载前显示个loading图&#xff0c;当组件加载出来就让这个loading图消失等等这样或那样的需求。 要实…

Java_JVM_JVMs

JVM 官方文档说明文档目录 官方文档 JVM Specification 说明 以Java SE 17为标准 文档目录 2&#xff1a;JVM 结构 class文件数据类型 基本数据类型引用数据类型 运行时数据区 栈帧 其他内容 对象的表示浮点数运算特殊方法 初始化方法【实例、类】多态方法 3&#xff…

【多变量控制系统 Multivariable Control System】(1)DSM:术语、基本公式和MATLAB仿真【新加坡南洋理工大学】

说明&#xff1a; 题目版权归校方所有&#xff0c;仅供学习和参考使用。 DSM Control DSM Direct Synthesis Method Process Model Closed-Loop Transfer Function 基本公式 &#xff08;1&#xff09;输入、输出关系 &#xff08;2&#xff09;控制器表示 MatLab仿真…

如何在Mac上恢复格式化硬盘的数据?

“嗨&#xff0c;我格式化了我的一个Mac硬盘&#xff0c;而没有使用Time Machine备份数据。这个硬盘被未知病毒感染了&#xff0c;所以我把它格式化为出厂设置。但是&#xff0c;我忘了备份我的文件。现在&#xff0c;我想恢复格式化的硬盘驱动器并恢复我的文档&#xff0c;您能…