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

【c语言数据结构】栈的详解! 超级详细!(模拟实现,OJ练习题)

目录

栈的概念:

栈的模拟实现

Stack.h

Stack.c

栈的相关OJ练习题

有效的括号

思路:

代码及解析


栈的概念:


栈:像是一种容器,东西只能从一个地方进,一个地方出,且后进先出!这是其和队列(先进先出,像排队一样,先到先得)的本质区别

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

入栈:插入数据在栈顶。

出栈:栈的删除操作。出数据也在栈顶。

栈的模拟实现

Stack.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>


//定义栈的结构
typedef int STDataType;
typedef struct Stack
{
    STDataType* arr;
    int capacity;//栈的空间大小
    int top;//栈顶(插入数据和删除数据的位置)
}ST;

//初始化
void STInit(ST* ps);//传的是地址

//销毁
void STDestory(ST* ps);

//栈顶-=--如数据、出数据

//栈的入数据操作
void SrackPush(ST* ps, STDataType x);//第二个参数是要插入的数据

//栈的出数据操作
void SrackPop(ST* ps);

//取栈顶元素---循环打印栈顶的数据
STDataType StackTop(ST* ps);//返回值是栈顶的元素

//判断栈是否为空
bool StackEmpty(ST* ps);

//获取栈中有效个数
int STSize(ST* ps);

Stack.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"
//初始化
void STInit(ST* ps) {
	assert(ps);//看文件是不是传空
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
	//初始的栈顶和栈底都为0(栈为空)
}

//销毁
void STDestory(ST* ps) {
	assert(ps);
	if (ps->arr != NULL) //栈不为空,说明里面有数据占用空间,直接将其释放掉

	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}

//栈顶-=--如数据、出数据
//入栈要判断空间是否满了(满了就没法加入数据了)
//出栈,取栈顶元素都要判断栈是否为空(空的栈你能取啥玩意啊)

//栈的入数据操作
void SrackPush(ST* ps, STDataType x) {
	assert(ps);

	//先判断空间情况,还能否加入数据!!!!!!!!!!
	if (ps->top == ps->capacity)//空间满了,需要增容
	{
		//一般情况是二倍的增加
		//初始情况下我们的capacity是定义为0的,所以我们不能直接进行乘二的操作
		//我们需要创建一个变量newCapacity
		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);
		}

		//申请成功,将tmp申请的空间给pa->arr
		ps->arr = tmp;
		ps->capacity = newCapacity;//容量增加
	}

	//到此为止,空间够够的了,可以放入数据了
	//往栈顶添加数据
	ps->arr[ps->top++] = x;
}



//判断栈是否为空
bool StackEmpty(ST* ps) {
	assert(ps);
	//return ps->arr == NULL;这是判断指针是否为空
	return ps->top == 0;
}
	//栈的出数据操作
void SrackPop(ST* ps) {
	assert(ps);
	//要判断是否栈为空!!!不然空栈怎么出数据!
	assert(!StackEmpty(ps));

	//走到这里就说明栈不为空
	--ps->top;//我们只需要将top进行--操作就能进行栈的出数据操作了
}

栈的出数据操作
//void SrackPopError(ST* ps) {
//	assert(ps);
//	return --ps->arr[ps->top];
//}




//取栈顶元素---循环打印栈顶的数据
STDataType StackTop(ST* ps) {
	assert(ps);
	assert(!StackEmpty(ps));//判断当前栈是不是空的,如果是空的话,我们没有什么能取的
	return ps->arr[ps->top-1];//类似数组,最后一个数据是top-1下标
}



//获取栈中有效个数
int STSize(ST* ps) {
	assert(ps);
	return ps->top;
}

栈的相关OJ练习题

有效的括号

思路:

①用指针ps遍历括号字符串

②ps遇到左括号->入栈,ps++继续向下走

    ps遇到右括号->在栈顶的左括号比较是否匹配

③两者匹配->出栈,ps++继续向下走,直至全部匹配,返回true

    两者不匹配->非有效括号,返回false,栈销毁

代码及解析

#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"
//定义栈的结构
typedef char STDataType;
typedef struct Stack
{
	STDataType* arr;
	int capacity;//栈的容量
	int top;//栈顶
}ST;

//初始化
void STInit(ST* ps) {
	assert(ps);
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}
//销毁
void STDestory(ST* ps) {
	assert(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 fail!");
			exit(1);
		}

		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
	ps->arr[ps->top++] = x;
}

//判断栈是否为空
bool StackEmpty(ST* ps) {
	assert(ps);
	return ps->top == 0;
}
//栈的出数据操作
void StackPop(ST* ps) {
	assert(ps);
	//判断数据是否为空
	assert(!StackEmpty(ps));

	--ps->top;
}

//取栈顶元素---循环打印栈顶的数据
STDataType StackTop(ST* ps) {
	assert(ps);
	assert(!StackEmpty(ps));

	return ps->arr[ps->top - 1];
}



//获取栈中有效个数
int STSize(ST* ps) {
	assert(ps);
	return ps->top;
}

bool isValid(char* s) {
	//创立新的栈
	ST S;
	//初始化
	STInit(&S);

	//取字符指针遍历括号字符串
	char* ps = s;
	while (*ps != '\0') {
		//判断是否是左括号,是->入栈
		if (*ps == '(' || *ps == '[' || *ps == '{') {
			StackPush(&S,*ps);
		}
		else//此时的ps是右括号->比较匹配左括号
		{
			//因为可能拿了左括号没有右括号,得先判断此时栈是否为空
			if (StackEmpty(&S))
				return false;
			//取目前栈顶的左括号保存在ch中,方便比较
			char ch = StackTop(&S);
			//若匹配
			if ((*ps == ')' && ch == '(') || (*ps == ']' && ch == '[') || (*ps == '}' && ch == '{')) {
				//将第一个栈顶左括号出栈
				StackPop(&S);
			}
			else//不匹配,是无效括号,直接返回错误
			{
				STDestory(&S);//返回前记得销毁
				return false;
			}
		}
		ps++;
	}
	bool ret = StackEmpty(&S) == true;//为空->全匹配完了->返回true
	//销毁
	STDestory(&S);
	return ret;
}


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

相关文章:

  • Macmini中普通鼠标与TrackPad联动问题解决
  • 图像基础算法学习笔记
  • Webpack 1.13.2 执行 shell 命令解决 打印时没有背景色和文字颜色的问题
  • 2024-11-17 -MATLAB三维绘图简单实例
  • 【阅读记录-章节1】Build a Large Language Model (From Scratch)
  • 腾讯云内容合规基于springboot架构设计
  • kubernetes K8S 挂载分布式存储 ceph
  • 算法基础8-双链表
  • Xcode16 iOS18 编译问题适配
  • 微信小程序教程:如何在个人中心实现头像贴纸功能
  • python爬虫解析工具BeautifulSoup(bs4)和CSS选择器——处理HTML和XML数据(7)
  • Windows系统修改Tomcat虚拟机内存参数
  • 《CUDA编程》3.简单CUDA程序的基本框架
  • 计算机毕业设计python+spark知识图谱房价预测系统 房源推荐系统 房源数据分析 房源可视化 房源大数据大屏 大数据毕业设计 机器学习
  • RuoYi-App根据不同角色权限实现功能按钮显隐
  • OpenHarmony(鸿蒙南向)——平台驱动指南【I2C】
  • 简易STL实现 | 红黑树的实现
  • SpringCloud-07 GateWay01 网关技术
  • 使用Okhttp-服务器不支持缓存的解决办法
  • C++之Person类
  • JavaScript中的无穷大
  • 华为静态路由(route-static)
  • 【Unity navigation面板】
  • 在 deepin 上除了 Steam,还能怎么玩游戏?
  • Python中性能优化与高级应用
  • Java律师法律咨询小程序