当前位置: 首页 > article >正文

数据结构:栈和队列详解(上)

一.栈

1.概念与结构:

栈:一种特殊的线性表,只允许在顺序表的一段插入和删除数据,进行插入和删除的一端叫做栈顶,另外一端则叫做栈底,而我们将在栈顶插入数据叫做压栈(入栈或进栈),在栈底删除数据则叫做出栈

栈的实现可以通过链表和数组实现,但数组在尾插时相对于需要遍历链表才能尾插的链表结构而言拥有更小的时间复杂度,所以栈的实现一般使用数组实现

2.栈的实现:

#pragma once
#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 STDestory(ST* ps);
//入栈
void StackPush(ST* ps, STDataType x);
//判断栈是否为空(配合确定top--至0(栈底)的限制条件)
bool StackEmpty(ST* ps);
//出栈
void StackPop(ST* ps);
//取栈顶数据
STDataType StackTop(ST* ps);
//获取栈中有效元素个数
STDataType STsize(ST* ps);
//栈的初始化
void STInit(ST* ps)
{
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}
//栈的销毁
void STDestory(ST*ps)
{
	if (ps->arr)
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}
//入栈
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	//空间不够
	if (ps->capacity == ps->top)
	{
		//扩容
		STDataType newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* tmp = (STDataType*)realloc(ps->arr, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc failed");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newcapacity;
	}
	//空间足够
	ps->arr[ps->top++] = x;
	ps->capacity++;
}
//判断栈是否为空
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}
//出栈
void StackPop(ST* ps)
{
	assert(!StackEmpty(ps));
	--ps->top;
	--ps->capacity;
}
//获取栈顶元素
STDataType StackTop(ST* ps)
{
	assert(!StackEmpty(ps));
	return ps->arr[ps->top-1];
}
//获取栈中元素个数
STDataType STsize(ST* ps)
{
	assert(ps);
	return ps->top;
}

以上是栈的实现中所有涉及的函数及函数实现

3.与栈有关的算法题(有效的括号):

原题来源:https://leetcode.cn/problems/valid-parentheses/description/

这题的主要思路就是通过创建一个栈,然后在对输入的一串字符串进行遍历入栈,首先是使其中的一个栈的入栈条件为”是左括号“,如果遍历出的下一个是与之对应的右括号,则使先前入栈的左括号出栈,以此类推,直至字符串遍历完成,如果此时栈为空,则说明字符串符符合题意并且返回true,若不为空,则返回false,整体来看,代码总体上会以字符串的遍历以及栈的输入输出为整体架构,并且伴随着对特殊情况1:”空栈“特殊情况2:”字符串遍历完后栈中是否还有元素残留“的讨论,前者应当置于字符串遍历过程中字符元素与栈元素的对比之前,因为对比就意味着要从栈里读取元素,而空栈是无法读取的,后者则应当置于尾部,在对比机制完整之后以防止”【】{“(类似这种情况)的产生,同时还有一点值得注意的就是每次排除一种错误情况时都不要忘记销毁栈(因为栈的插入涉及到对空间的申请,而不及时释放空间就很容易产生内存泄漏问题)


//栈的初始化
void STInit(ST* ps)
{
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}
//栈的销毁
void STDestory(ST* ps)
{
	if (ps->arr)
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}
//入栈
void StackPush(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 failed");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newcapacity;
	}
	//空间足够
	ps->arr[ps->top++] = x;
	ps->capacity++;
}
//判断栈是否为空
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}
//出栈
void StackPop(ST* ps)
{
	assert(!StackEmpty(ps));
	--ps->top;
	--ps->capacity;
}
//获取栈顶元素
char StackTop(ST* ps)
{
	assert(!StackEmpty(ps));
	return ps->arr[ps->top - 1];
}
//获取栈中元素个数
int STsize(ST* ps)
{
	assert(ps);
	return ps->top;
}








bool isValid(char* s) {
ST st;
STInit(&st);
char* pi = s;
//遍历字符串
while (*pi != '\0')
{

    //左括号入栈
    if (*pi == '{' || *pi == '[' || *pi == '(')
    {
        StackPush(&st, *pi);
    }
    else
    {//右括号取栈顶并匹配
    //先判断是否为空
        if (StackEmpty(&st))
        {
            STDestory(&st);
            return false;
        }
        char tmp = StackTop(&st);
        if (tmp == '{' && *pi! = '}' || tmp == '(' && *pi! = ')' || tmp == '[' && *pi! = ']')
        {
            STDestory(&st);
            return false;
        }
        StackPop(&st);
    }
    pi++;
}
//如果栈为空,说明所有的括号都匹配完了,反之为非有效字符串
bool ret = StackEmpty(&st) ? true : false;
STDestory(&st);
return ret;
}


http://www.kler.cn/a/511502.html

相关文章:

  • 重温STM32之环境安装
  • windows蓝牙驱动开发-蓝牙设备栈
  • DETR论文阅读
  • uni-app vue3 常用页面 组合式api方式
  • Web前端------表单标签
  • nuiapp在APP中的.nvue页面中使用webview展示空白的问题
  • 郑州大学2022级大三期末复习总结(数据库,传感器,嵌入式,人工智能,移动终端开发,计算机英语)
  • Unity中不使用场景和预制体保存关卡信息(附源文件)
  • Gitblit 一些使用说明记录
  • 【React】静态组件动态组件
  • Jetpack 介绍
  • 删除字符串中的所有相邻重复项(力扣1047)
  • 怎么投稿各大媒体网站?如何快速辨别一家媒体是否适合自己?
  • 2025年01月17日Github流行趋势
  • 资源管理模块集成Spring Cache
  • 【Linux系统编程】—— 深度解析进程等待与终止:系统高效运行的关键
  • TCP状态转移图详解
  • 【数据结构-堆】【hard】力扣502. IPO
  • 【opencv】第10章 角点检测
  • Kinova仿生机械臂Gen3搭载BOTA 力矩传感器SeneOne:彰显机器人触觉 AI 与六维力传感的融合力量
  • StarRocks 怎么让特定的SQL路由到FE master节点的
  • 推荐sdkman管理sdk和jdk
  • Java 基于 SpringBoot+Vue 的停车场管理系统(附源码,部署,文档)
  • 神经网络常见面试题
  • MySQL 主从复制原理及其工作过程的配置
  • Flowable 管理各业务流程:流程设计器 (获取流程模型 XML)、流程部署、启动流程、流程审批、流程挂起和激活、任务分配