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

一、问题引入

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

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

号码位置对应的括号之间进行匹配,结果: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语言实现猜数字游戏的完整攻略: 实现步骤 1.首先,打开C语言编译器,创建一个新的工程。 2.在代码文件中,需要先引入需要用到的头文件: #include <s…

    C 2023年5月23日
    00
  • C语言栈帧的组织

    C语言中函数调用的过程中,每个函数调用都会创建一个栈帧,栈帧用来存储函数的参数、局部变量和一些执行状态。C语言栈帧的组织是指在函数调用的过程中,如何使用堆栈的方式来组织栈帧。下面是C语言栈帧的组织的详细使用攻略: 1. 栈帧的组成 C语言函数调用产生的栈帧通常由以下几个部分组成: 函数参数 返回地址 前一个函数的栈帧指针 局部变量 临时寄存器 其中,函数参数…

    C 2023年5月9日
    00
  • Android NDK开发(C语言基本数据类型)

    Android NDK开发(C语言基本数据类型)攻略 什么是Android NDK? Android NDK(Native Development Kit)是一个允许您使用C和C++代码在Android设备上开发应用程序的工具集。NDK允许您在Android应用程序中使用底层C和C++代码,从而提高应用程序性能。使用NDK可以实现以下功能: 构建基于C/C+…

    C 2023年5月24日
    00
  • 深入理解C++模板如何实现多态思想

    深入理解C++模板如何实现多态思想 C++模板是一种高度通用化的编程工具,除了可以用来实现代码复用之外,还可以用来实现多态的编程思想。在这里,我将详细介绍如何使用C++模板来实现多态的思想,涵盖泛型编程、函数模板、类模板等方面。 一、泛型编程泛型编程是C++模板多态思想的最基本组成部分,其核心思想是将数据类型与算法分离,从而实现代码的通用化。在使用C++模板…

    C 2023年5月23日
    00
  • C语言编程中函数的基本学习教程

    C语言编程中函数的基本学习教程 1. 函数的定义及使用方法 C语言中函数是一块可重用的、能实现特定功能的代码块,它以函数名作为标识符,一旦定义就可以在程序的任何地方被调用。C语言中函数的定义通常包含返回值类型、函数名以及函数参数,具体格式如下: 返回值类型 函数名(参数列表) { // 函数体 } 其中,返回值类型是指函数返回值的数据类型,函数名是指函数的名…

    C 2023年5月23日
    00
  • C语言各种符号的使用介绍下篇

    C语言各种符号的使用介绍 1. 赋值操作符 赋值操作符=用于将表达式右边的值赋给左边的变量。例如: int a; a = 10; 上述代码中,将整数值10赋值给变量a。 2. 算术操作符 2.1 加法操作符 加法操作符+用于将两个值相加。例如: int a = 10; int b = 20; int c = a + b; 上述代码中,将变量a和b的值相加,将…

    C 2023年5月23日
    00
  • JavaScript ES6解构运算符的理解和运用

    JavaScript ES6解构运算符的理解和运用 简介 ES6引入了解构运算符(destructuring assignment),该运算符提供了一种灵活且直观的方式来进行数组或对象的解构赋值,能够大大简化代码的书写和编写效率。本文将深入探讨ES6解构运算符的理解和运用。 数组解构 通过解构运算符可以将数组中的元素解构出来,并赋值给多个变量。下面是一个例子…

    C 2023年5月23日
    00
  • 详解linux lcd驱动编写

    下面是“详解linux lcd驱动编写”的完整攻略: 一、为什么需要编写LCD驱动 在嵌入式开发中,我们通常会使用液晶显示屏来展示用户界面。而LCD显示屏的操作需要进行硬件操作,因此我们需要编写LCD驱动来实现对显示屏的驱动控制。在Linux系统中,我们也需要编写相应的LCD驱动来实现显示控制。 二、lcd驱动编写的基本流程 编写Linux环境下的lcd驱动…

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