栈(顺序)的实现:括号的解析

一、问题引入

在学习栈的过程中,教材有一个案例:利用栈结构解析括号的匹配问题。括号问题:[({}{})],说明 [](){} 称为一对且满足就近匹配。

栈(顺序)的实现:括号的解析

号码位置对应的括号之间进行匹配,结果:0-71-62-34-5

源码链接https://github.com/caojun97/Bracket_Match

二、过程记录

2-1 栈的介绍

栈按照存储结构可以划分为:顺序栈 和 链栈。 顺序栈空间是固定上限的,入栈到固定上限就不能再执行入栈操作。而链栈就没有这种固定上限,上限取决与系统内存上限。

定义:栈(stack) 是限定仅在表尾进行插入或删除操作的线性表。
因此,对栈来说,表尾端有其特殊含义,称为栈顶(top), 相应地,表头端称为栈底(bottom)。不含元素的空表称为空栈

栈(顺序)的实现:括号的解析

利用栈的特性:先进后出 ,对括号进行匹配输出

栈(顺序)的实现:括号的解析

对栈的基本操作进行抽象定义函数:

  • 栈初始化

  • 入栈

  • 出栈

  • 栈销毁

2-2 数据结构定义

#define MAXSIZE 100 // 顺序栈存储空间的初始分配量

#define ERROR -1
#define OK 0
#define OVERFLOW 1

typedef struct
{
	char bracket;  // 存储括号字符
	int  idx;      // 存储括号字符索引
}BracketInfo;

typedef struct
{
	BracketInfo *base;      // 栈底指针
	BracketInfo *top;       // 栈顶指针
	int  stack_size;        // 栈可用的最大容量
	int  num_of_elem;       // 栈中元素数量
}SqStack_T;

2-3 栈操作定义

  • 栈初始化
int stack_init(SqStack_T *sq_stack_pt)
{
	/* base为栈底指针,初始化完成后,栈底指针base始终指向栈底位置.
	 * 若base的值为NULL,则表明栈结构不存在。
	*/
	sq_stack_pt->base = (BracketInfo *)malloc(MAXSIZE * sizeof(BracketInfo));
	if (NULL == sq_stack_pt->base)
	{
		//printf("malloc memory fail\n");
		exit(OVERFLOW); // 退出程序
	}
	sq_stack_pt->top = sq_stack_pt->base;
	sq_stack_pt->stack_size = MAXSIZE;
	sq_stack_pt->num_of_elem = 0;
	return OK;
}
  • 入栈
int stack_push(SqStack_T *sq_stack_pt, BracketInfo elem)
{
	// 入栈前,先判断是否栈满
	if (sq_stack_pt->base - sq_stack_pt->top == sq_stack_pt->stack_size)
	{
		printf("stack full\n");
		return ERROR;
	}
	// 元素入栈,栈顶指针top+1
	*(sq_stack_pt->top) = elem;
	(sq_stack_pt->top)++;
	(sq_stack_pt->num_of_elem)++;
	return OK;
}
  • 出栈
int stack_pop(SqStack_T *sq_stack_pt, BracketInfo *elem)
{
	// 出栈前,先判断是否栈空
	if (sq_stack_pt->top == sq_stack_pt->base)
	{
		printf("stack empty\n");
		return ERROR;
	}
	// 元素出栈,栈顶指针top-1
	(sq_stack_pt->top)--;
	(sq_stack_pt->num_of_elem)--;
	*elem = *(sq_stack_pt->top);
	return OK;
}
  • 取栈顶元素
BracketInfo stack_top_element_get(SqStack_T sq_stack_t)
{
	BracketInfo elem = { 0 };
	if (sq_stack_t.top != sq_stack_t.base)
		elem = *(sq_stack_t.top - 1);
	return elem;
}
  • 栈销毁
void stack_destory(SqStack_T *sq_stack_pt)
{
	if (sq_stack_pt->base != NULL)
		free(sq_stack_pt->base);
	sq_stack_pt->base = NULL;
	sq_stack_pt->top = NULL;
	sq_stack_pt->num_of_elem = 0;
}

2-4 main函数

? 数据结构的定义和栈操作的定义都放在文件 sq_stack.hsq_stack.c 中。程序是基于顺序栈实现的

#include "sq_stack.h"
#include <stdio.h>

int main(void)
{
	SqStack_T sq_stack_t;
	stack_init(&sq_stack_t);
	char buffer[50] = { "[({}{})]" };
	int buffer_len = strlen(buffer);
	for (int i = 0; i < buffer_len; i++)
	{
		if (buffer[i] == '[' || buffer[i] == '(' || buffer[i] == '{')
		{
			BracketInfo elem = { 0 };
			elem.idx = i;
			elem.bracket = buffer[i];
			stack_push(&sq_stack_t, elem); // 入栈
		}
		else if (buffer[i] == ']' || buffer[i] == ')' || buffer[i] == '}')
		{
			BracketInfo elem_top = { 0 }, elem = {0};
			elem_top = stack_top_element_get(sq_stack_t);
			if (buffer[i] == ']')
			{
				if (elem_top.bracket == '[')
				{
					stack_pop(&sq_stack_t, &elem); // 出栈
				}
			}
			else if (buffer[i] == ')')
			{
				if (elem_top.bracket == '(')
				{
					stack_pop(&sq_stack_t, &elem); // 出栈
				}
			}
			else if (buffer[i] == '}')
			{
				if (elem_top.bracket == '{')
				{
					stack_pop(&sq_stack_t, &elem); // 出栈	
				}
			}
			if(elem.bracket == 0)
				printf("  %c    (-1,%d)\n", buffer[i], i);
			else
				printf("%c %c    (%d,%d)\n", elem.bracket, buffer[i], elem.idx, i);
		}
	}
	stack_destory(&sq_stack_t);
	return 0;
}

栈(顺序)的实现:括号的解析

  • 修改输入buffer

char buffer[50] = { "[a*(b+c)-d*(e-f)]" };

栈(顺序)的实现:括号的解析

三、反思总结

将数据结构结合实际项目进行学习和理解才能事半功倍。栈-数据结构是固定,思考应用场景能否利用栈结构实现。

四、参考引用

数据结构第二版:C语言版 【严蔚敏】

原文链接:https://www.cnblogs.com/caojun97/p/17246869.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:栈(顺序)的实现:括号的解析 - Python技术站

(0)
上一篇 2023年4月18日
下一篇 2023年4月18日

相关文章

  • C语言循环链表的原理与使用操作

    C语言循环链表是一种基于链表数据结构的可循环访问的存储方式。与线性表相比,链表能够优化数据的插入和删除操作的效率,并且支持动态的内存分配。而循环链表则定义了表头尾相接,最后一个节点指向第一个节点的链表。下面将详细讲解循环链表的原理、使用操作及其实现过程,以及两个示例进行说明。 原理 循环链表是由多个节点组成的链式结构,每个节点包含自身的数据和指向下一个节点的…

    C 2023年5月24日
    00
  • Python操作MySQL MongoDB Oracle三大数据库深入对比

    Python操作MySQL MongoDB Oracle三大数据库深入对比 本文将介绍如何使用Python对MySQL、MongoDB和Oracle三大数据库进行操作,并从安装、连接、基本操作、性能等多个方面进行深入对比。 环境配置 MySQL 首先需要安装MySQL数据库,可以去官网下载MySQL Installer,然后按照指引完成安装。 安装完成后,需…

    C 2023年5月23日
    00
  • win10开机蓝屏代码0xc000001怎么办 错误代码0xc000001的解决教程

    Win10开机蓝屏代码0xc000001怎么办 错误代码0xc000001的解决教程 在Windows 10系统使用电脑时,经常会遇到蓝屏问题,如果蓝屏提示代码为0xc000001,可能是由于系统文件损坏或系统启动设置不正确引起,下面是解决方法: 方法1:使用Windows Startup Repair Windows Startup Repair是Wind…

    C 2023年5月23日
    00
  • C字符串操作函数的实现详细解析

    C字符串操作函数的实现详细解析 1. 什么是C字符串 C语言中的字符串是由一组字符序列组成,以’\0’(空字符)结尾,其在内存中的存储方式是顺序存储的字符数组。由于C语言本身并没有提供字符串类型,所以需要通过字符数组及一些函数来操作字符串。 2. 常用C字符串操作函数 常用的C字符串操作函数有以下几种: strlen:计算字符串的长度 strcpy:将一个字…

    C 2023年5月23日
    00
  • Python中Random和Math模块学习笔记

    当谈到随机数生成,Python自带的random模块和math模块是帮助我们处理这些任务的重要组件。这两个库都允许我们使用Python进行随机数生成操作,它们之间也存在着一些区别,下面我来详细讲解一下这两个模块的使用。 Random模块 Random模块是Python自带的标准库之一,可以用于生成随机数和从序列中作出随机选择。下面是一个简单的示例,展示了如何…

    C 2023年5月22日
    00
  • C++线程安全的单例模式讲解

    下面我将为您详细讲解“C++线程安全的单例模式讲解”的完整攻略。 什么是单例模式? 单例模式是一种创建型设计模式,它可以保证一个类在任何情况下都只有一个实例,并且提供了一个全局访问点来访问该实例。在单例模式中,类的构造函数是私有的,所以无法通过常规方法创建新的实例。单例模式通常被用来控制资源访问,如数据库连接的单例。 为什么要使用线程安全的单例模式? 当一个…

    C 2023年5月22日
    00
  • 从零学习cmake构建系统

    下面我将详细讲解“从零学习CMake构建系统”的完整攻略。 什么是 CMake CMake 是一个开源跨平台的构建系统,可以用于管理源代码,生成各个平台的构建文件(例如 Makefile 或 Visual Studio Solution),从而实现构建和编译。使用 CMake 可以使得跨平台的程序的编写和构建变得更加简单和高效。 安装 CMake CMake…

    C 2023年5月23日
    00
  • C语言圣诞树的实现示例

    C语言圣诞树的实现示例 在这个示例中,我们将会使用C语言来实现一个圣诞树的输出效果。代码中将会用到循环、条件语句、字符输出、延时等知识点,让我们一起来看看该如何实现吧。 实现思路 实现圣诞树的思路很简单,我们可以分成两个部分来实现: 打印出圣诞树的形状,包括树干和树叶部分。 在圣诞树上挂上圣诞灯,增添节日气氛。 代码实现 基本思路讲解完了,我们来看看代码: …

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部