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

一、问题引入

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

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

号码位置对应的括号之间进行匹配,结果: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语言实现一个简单的员工工资管理系统。该系统可以用于输入员工基本信息,录入工资数据和计算每个员工的工资。其主要功能模块包括:输入员工基本信息、录入工资数据、计算员工工资、显示员工工资信息。 基本功能 输入员工基本信息:包括员工的姓名、性别、年龄、工龄等信息。 示例代码: “`c struct emp…

    C 2023年5月23日
    00
  • C++中的编译与链接

    C++中的编译与链接是将源代码转换为可执行文件的过程。它分为三个阶段:预处理、编译和链接。 预处理 预处理是C++编译过程的第一个阶段,该阶段将源文件中的预处理指令处理为有效的C++代码。 预处理器在编译之前会检查源文件并执行以下操作: 处理所有以 “#” 开头的预处理指令。 删除所有注释(// 和 / /)。 将所有 #include 指令替换为相应头文件…

    C 2023年5月23日
    00
  • YOGA C740和YOGA C940应该如何选择 YOGA C740和YOGA C940详细评测对比

    YOGA C740和YOGA C940应该如何选择 硬件配置 YOGA C940和YOGA C740在硬件配置上有一定的差异,如下所示: 参数 YOGA C740 YOGA C940 CPU Intel i5/i7 Intel i7/i9 内存 8/12/16GB 8/12/16GB 存储 256/512/1TB 256/512/1TB 显卡 NVIDIA …

    C 2023年5月23日
    00
  • 一加8T怎么样?一加8T屏幕、拍照、性能等全面评测

    一加8T全面评测 一加8T基本信息 发布时间:2020年10月 屏幕尺寸:6.55英寸 像素密度:402ppi 分辨率:2400*1080 FHD+ AMOLED 处理器:高通骁龙865 一加8T屏幕评测 一加8T采用了6.55英寸FHD+ AMOLED屏幕,像素密度为402ppi,分辨率达到2400*1080。屏幕亮度高,色彩鲜艳饱满。HDR10+支持带来…

    C 2023年5月22日
    00
  • Java中怎样使用JSON进行文件解析

    使用 JSON(JavaScript Object Notation)进行文件解析是 Java 中经常进行的操作之一。下面是一些使用 Java 解析 JSON 文件的步骤: 步骤一:导入 JSON 库 Java 中有许多 JSON 库可供选择,比如 GSON 和 Jackson。这里我们以 GSON 为例进行说明。首先需要在项目中导入 GSON 库,可以使用…

    C 2023年5月23日
    00
  • AJAX开发简略 (第二部分)

    下面我来详细讲解“AJAX开发简略 (第二部分)”的完整攻略。 AJAX开发简略(第二部分) 在上一篇文章中,我们已经了解到 AJAX 的定义、用途和基本的使用方法。本篇文章将介绍如何使用 AJAX 进行数据交互,以及如何避免常见的 AJAX 开发问题。 数据交互 AJAX 最常见的用途就是向服务器获取数据并更新页面,而且这个过程是异步进行,不会阻塞页面加载…

    C 2023年5月22日
    00
  • python math模块使用方法介绍

    Python math模块使用方法介绍 Python的math模块是一个十分强大的数学库,提供许多数学函数和常数。下面将对math模块的使用方法进行详细介绍。 导入math模块 使用math模块前,需要先导入该模块。可以使用以下方式进行导入: import math 常用的math函数 math模块提供了许多数学函数,这里列举一些常用的函数: math.ce…

    C 2023年5月22日
    00
  • C语言实现牛顿迭代法解方程详解

    C语言实现牛顿迭代法解方程详解 简介 牛顿迭代法是一种数值分析方法,用于查找方程的实根。它一般适用于函数不容易被直接求解的情况。本文将介绍如何使用C语言实现牛顿迭代法解方程。 具体步骤 根据题意,手动计算求出方程的一阶导数和二阶导数,并保存到程序中。 根据求导公式,编写程序计算函数的导数。假设方程为 $f(x)$,则 $f'(x)$ 的计算公式为: doub…

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