数据结构(栈)

文章目录


一、概念与结构

  • 栈:⼀种特殊的线性表,其只允许在固定的⼀端进⾏插⼊和删除元素操作。进⾏数据插⼊和删除操作的⼀端称为栈顶,另⼀端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
  • 压栈:栈的插⼊操作叫做进栈/压栈/⼊栈,⼊数据在栈顶。
  • 出栈:栈的删除操作叫做出栈。出数据也在栈顶。

栈的实现⼀般可以使⽤数组或者链表实现,相对⽽⾔数组的结构实现更优⼀些。因为数组在尾上插⼊数据的代价⽐较⼩。 一般使用数组作为栈的底层结构对栈的出栈压栈更方便)

二、栈的实现

stack.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>


typedef int STDataType;
typedef struct Stack
  {
	 STDataType* arr;
	 int top;
	 int capacity;
	 }ST;

 // 初始化栈
 void STInit(ST * ps);
 // 销毁栈
 void STDestroy(ST * ps);

 // ⼊栈
 void STPush(ST * ps, STDataType x);
 //出栈
 void STPop(ST * ps);

 //取栈顶元素
 STDataType STTop(ST * ps);

 //获取栈中有效元素个数
 int STSize(ST * ps);
 
 //栈是否为空
bool STEmpty(ST * ps);

stack.c

初始化栈
void STInit(ST* ps)
{
	assert(ps);
	ps->arr = NULL;
	ps->capacity = ps->top = 0;

}
销毁栈
void STDestroy(ST* ps)
{
	assert(ps);
	if (ps->arr)
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}
入栈
void STPush(ST* ps, STDataType x)
{
	assert(ps);
	if(ps->capacity==ps->top)    //空间满了
	{ 
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
	    STDataType* tmp = (STDataType*)realloc(ps->arr, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newcapacity;
	
	}
	//空间足够,直接插入
	ps->arr[ps->top] = x;
	ps->top++;
}

出栈
bool STEmpty(ST* ps)     
{
	assert(ps);
	return ps->top == 0;    //若栈为空则返回 true
}

void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty);   //若栈不为空 ,则返回false,(!false)就为 true

	--ps->top;             //直接 --top

}

取栈顶元素
STDataType STTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));


	return ps->arr[ps->top - 1]; //直接返回栈顶位置,数组是由下标表示,这里记得 top-1
}
 
获取栈中有效元素个数
int STSize(ST* ps)
{
	assert(ps);

	return ps->top;
}

test.c

#include"stack.h"

void STTest()
{
	ST st;
	STInit(&st);
	//
	STPush(&st, 1);
	STPush(&st, 2);
	STPush(&st, 3);
	STPush(&st, 4);
	

	//循环打印出栈数据
	while (!STEmpty(&st))
	{
		STDataType data = STTop(&st);
		printf("%d", data);

		STPop(&st);
	}
	printf("\n栈中的有效个数:%d\n", STSize(&st));

	STDestroy(&st);
}

int main() {
	STTest();
	
	return 0;
}

 

  • 往栈顶插入数据:

 

  •  //循环打印出栈数据,直到栈为空

 

 三、有效括号(算法题)20. 有效的括号 - 力扣(LeetCode)

  • 下面利用栈的特点来解决一道算法题 

先利用上述栈的实现函数定义一个结构体,并且初始化。

bool isValid(char* s) {
    ST st;
    STInit(&st);

    // 遍历字符串 s
    char* ps = s;
    while (*ps != '\0') {
        // 左括号,入栈
        if (*ps == '(' || *ps == '[' || *ps == '{') 
        {
            STPush(&st, *ps);
        }
       
        // 右括号,和栈顶元素比较是否能匹配
        else {
            // 栈为空,直接返回false,意思就是 *ps == 右括号 这种情况
            if (STEmpty(&st)) 
            {
                return false;
            }

            // 当存在左括号,即入栈了,栈不为空才能取栈顶元素
            // 取栈顶元素
            char a = STTop(&st);
            if ((*ps == ')' && a == '(') 
            || (*ps == ']' && a == '[') 
            || (*ps == '}' && a == '{')) 
            {
                // 出栈
                STPop(&st);
            }

            // 当只存在左括号:
            else {
                STDestroy(&st);
                return false;
            }
        }
        ps++;
    }

    // 当ps和a中的符号都能匹配完成,元素全部出栈,栈为空,返回true
    bool ret = STEmpty(&st);
    STDestroy(&st);
    return ret;
}

思路:

  • 用字符指针 *ps 遍历字符串
  • 若 ps 遍历到的字符为左括号 ,入栈
  • 若 ps 遍历到的字符为右括号,1)取栈顶元素,与 ps 进行比较 

                                                        2)栈顶元素匹配 *ps,出栈,ps++ ,直至所有元素匹配,全部元素出栈,栈为空,返回false

                                                        3)栈顶元素不匹配 *ps,直接返回false 

未完待续~~

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在qt的c++程序嵌入一个qml窗口

//拖拽一个QQuickWidget c端和qml通信的桥梁 找到qml的main.qml的路径 ui->quickWidget->setSource(QUrl::fromLocalFile("../../../code/main.qml"));// QML 与 Qt Widgets 通信//窗口就成了一个类实例对象pRoot (QObject*)ui->quickWidget->rootObje…

操作系统:408考研|王道|学习笔记

系列目录 计算机组成原理 学习笔记I 计算机组成原理 学习笔记II 目录 系列目录第1章 计算机系统概述1.1 操作系统的基本概念1.1_1 操作系统的定义、功能1.1_2 操作系统的特征 1.2 操作系统的发展与分类1.3 操作系统的运行环境&#x1f31f;1.3_1 操作系统的运行机制&#x1f3…

防溺水预警系统引领水域安全新篇章

一、系统概述 随着人们对水域活动的需求增加&#xff0c;溺水事故频发&#xff0c;给人们的生命安全带来了严重威胁。然而&#xff0c;如今&#xff0c;一项创新科技正在以强大的功能和无限的潜力引领着水域安全的新篇章。智能防溺水预警系统&#xff0c;作为一种集成了智能感知…

SwiftUI 5.0(iOS 17)滚动视图的滚动目标行为(Target Behavior)解惑和实战

概览 在 SwiftUI 的开发过程中我们常说&#xff1a;“屏幕不够&#xff0c;滚动来凑”。可见滚动视图对于超长内容的呈现有着多么秉轴持钧的重要作用。 这不&#xff0c;从 SwiftUI 5.0&#xff08;iOS 17&#xff09;开始苹果又为滚动视图增加了全新的功能。但是官方的示例可…

不懂商业模式,没有互联网思维,不建议创业

在当今商业浪潮中&#xff0c;作为企业的掌舵人&#xff0c;若对商业模式缺乏深刻理解&#xff0c;确实容易陷入亏损与负债的困境&#xff0c;尤其是在互联网与创业领域。成功的企业往往建立在坚实的商业模式之上&#xff0c;这里我将为您概述五种关键模式&#xff0c;助力您把…

【go】Excelize处理excel表 带合并单元格、自动换行与固定列宽的文件导出

文章目录 1 简介2 相关需求与实现2.1 导出带单元格合并的excel文件2.2 导出增加自动换行和固定列宽的excel文件 1 简介 之前整理过使用Excelize导出原始excel文件与增加数据校验的excel导出。【go】Excelize处理excel表 带数据校验的文件导出 本文整理使用Excelize导出带单元…

Android 消息发布订阅框架:EventBus

目录 1.是什么 2.如何使用 3.五种线程模型 4.Eventbus2和Eventbus3的区别 一、是什么 EventBus是一款发布/订阅事件总线的框架&#xff0c;使用它可以进行模块间通信、解耦。它可以使用很少的代码&#xff0c;来实现多组件之间的通信&#xff0c;非常的方便。 为什么使用它…

十七、(正点原子)Linux LCD驱动

一、Framebuffer设备 在 Linux 中应用程序通过操作 RGB LCD 的显存来实现在 LCD 上显示字符、图片等信息。 先来看一下裸机 LCD 驱动如下&#xff1a; ①、初始化 I.MX6U 的 eLCDIF 控制器&#xff0c;重点是 LCD 屏幕宽(width)、高(height)、 hspw、 hbp、 hfp、 vspw…

go中map

文章目录 Map简介哈希表与Map的概念Go语言内建的Map类型Map的声明Map的初始化Map的访问Map的添加和修改Map的删除Map的遍历 Map的基本使用Map的声明与初始化Map的访问与操作Map的删除Map的遍历Map的并发问题实现线程安全的Map 3. Map的访问与操作3.1 访问Map元素代码示例&#…

微信小程序 button样式设置为图片的方法

微信小程序 button样式设置为图片的方法 background-image background-size与background-repeat与border:none;是button必须的 <view style" position: relative;"><button class"customer-service-btn" style"background-image: url(./st…

新华三H3CNE网络工程师认证—VLAN使用场景与原理

通过华三的技术原理与VLAN配置来学习&#xff0c;首先介绍VLAN&#xff0c;然后介绍VLAN的基本原理&#xff0c;最后介绍VLAN的基本配置。 文章目录 一、传统以太网问题1、广播域范围过大2、分割广播域 二、如何实现VLAN1、VLAN技术达到的效果2、VLAN数值的编号范围3、仿真&am…

这届打工人,快把单休卷成职场用工标配了……

最近&#xff0c;小柴有个朋友跟小柴吐槽&#xff0c;自己被「灵活就业」大半年了&#xff0c;有点扛不住&#xff0c;就准备去送外卖&#xff0c;结果第一天赚了38&#xff0c;反手电瓶车罚了50…… 心灰意冷的他&#xff0c;最终还是在某BOSS上充个值&#xff0c;没日没夜的投…

手持式气象站:便携科技,掌握微观气象的利器

手持式气象站&#xff0c;顾名思义&#xff0c;是一种可以随身携带的气象监测设备。它小巧轻便&#xff0c;通常配备有温度、湿度、风速、风向、气压等多种传感器&#xff0c;能够实时测量并显示各种气象参数。不仅如此&#xff0c;它还具有数据存储、数据传输、远程控制等多种…

搭建博客系统#Golang

WANLI 博客系统 项目介绍 基于vue3和gin框架开发的前后端分离个人博客系统&#xff0c;包含md格式的文本编辑展示&#xff0c;点赞评论收藏&#xff0c;新闻热点&#xff0c;匿名聊天室&#xff0c;文章搜索等功能。 点击跳转&#xff1a;Github 项目开源地址 功能展示 B 站…

实战篇(十):使用Processing创建可爱花朵:实现随机位置、大小和颜色的花朵

使用Processing创建可爱花朵 0.效果预览1. 引言2. 设置Processing环境3. 创建花朵类4. 实现花瓣绘制5. 绘制可爱的笑脸6. 鼠标点击生成花朵7. 完整代码8. 总结与扩展0.效果预览 在本教程中,我们将使用Processing编程语言来创建一个可爱的花朵生成器。通过封装花朵为一个类,并…

使用shedlock实现分布式互斥执行

前言 前序章节&#xff1a;springboot基础(82):分布式定时任务解决方案shedlock 如果你不清楚shedlock&#xff0c;建议先阅读前序章节&#xff0c;再来查看本文。 如果我们不在spring环境下&#xff0c;如何使用shedlock实现分布式互斥执行&#xff1f; 我们可以使用shedl…

Elasticsearch 7.x入门学习-Java API操作

1 创建项目 在idea开发工具中创建Maven项目 修改 pom 文件&#xff0c;增加 Maven 依赖关系 <dependencies><dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.8.0</versi…

ubuntu2204配置anacondacuda4090nvidia驱动

背景 某个机房的几台机器前段时间通过dnat暴露至公网后被入侵挖矿&#xff0c;为避免一些安全隐患将这几台机器执行重装系统操作&#xff1b; 这里主要记录配置nvidia驱动及cuda&anaconda。 步骤 大概分为几个步骤 禁用nouveau配置grub显示菜单install nvidia-driveri…

Linux云计算 |【第一阶段】ENGINEER-DAY3

主要内容&#xff1a; LVM逻辑卷管理、VDO、RAID磁盘阵列、进程管理 一、新建逻辑卷 1、什么是逻辑卷 逻辑卷&#xff08;Logical Volume&#xff09;是逻辑卷管理&#xff08;Logical Volume Management&#xff0c;LVM&#xff09;系统中的一个概念。LVM是一种用于磁盘管理…

SpringBoot集成MQTT实现交互服务通信

引言 本文是springboot集成mqtt的一个实战案例。 gitee代码库地址&#xff1a;源码地址 一、什么是MQTT MQTT&#xff08;Message Queuing Telemetry Transport&#xff0c;消息队列遥测传输协议&#xff09;&#xff0c;是一种基于发布/订阅&#xff08;publish/subscribe&…