前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【c语言数据结构】栈的详解! 超级详细!(模拟实现,OJ练习题)

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

作者头像
用户11292525
发布2024-09-27 08:20:01
1050
发布2024-09-27 08:20:01
举报
文章被收录于专栏:学习

栈的概念:

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

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

入栈:插入数据在栈顶。

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

栈的模拟实现

Stack.h

代码语言:javascript
复制
#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

代码语言:javascript
复制
#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,栈销毁

代码及解析
代码语言:javascript
复制
#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;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-09-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 栈的概念:
  • 栈的模拟实现
    • Stack.h
      • Stack.c
      • 栈的相关OJ练习题
        • 有效的括号
          • 思路:
          • 代码及解析
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档