C语言实现栈--数据结构

news2024/11/15 10:32:08

在这里插入图片描述

  • 魔王的介绍:😶‍🌫️一名双非本科大一小白。
  • 魔王的目标:🤯努力赶上周围卷王的脚步。
  • 魔王的主页:🔥🔥🔥大魔王.🔥🔥🔥
    请添加图片描述
    ❤️‍🔥大魔王与你分享:“断剑重铸的锐雯败于菲奥娜,原来破镜重圆的爱到处都是破绽”。

文章目录

  • 一、前言
    • 1、介绍
    • 2、说明
  • 二、栈的实现
    • 1、创建结构体
    • 2、初始化和销毁
    • 3、入栈
    • 4、出栈
    • 5、元素个数
    • 6、判断是否为空
    • 7、栈顶元素
  • 三、总代码
    • Stack.h
    • Stack.c
    • Test.c
  • 四、总结

一、前言

1、介绍

栈是一种特殊的线性表,其只允许在固定的一端插入和删除元素,进行插入和删除的一端称为栈顶,另一端称为栈底,栈中的数据元素遵循后进先出(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈。入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。

在这里插入图片描述

2、说明

栈的实现可以采用顺序表或链表,顺序表就是按顺序存进去(尾插),然后出的时候需要从后往前出。链表的话我们一边采用头插,因为如果是尾插的话,还要有前一个的地址,比头插麻烦一点,所以链表实现一般采用头插。
相对来说数组(顺序表)实现更优一些,因为数组在尾上插入数据代价更小。
如果顺序表和链表你已经掌握,那么相信栈和队列对你来说都是很简单的,因为它们只是对顺序表和链表进行特殊处理而已。

  • 本篇将通过顺序表实现栈。

二、栈的实现

1、创建结构体

我们需要创建一个结构体来存放数组指针和该数组的元素个数及数组的容量。

代码:

typedef int STDateType;

typedef struct Stack
{
	STDateType* a;
	int top;//如果初始化为0,可以理解为元素个数(也就是栈顶元素下标+1),如果初始化为-1,可以理解为栈顶元素的下标
	int capacity;
}ST;

2、初始化和销毁

初始化:
就像顺序表一样,我们需要首先开辟一个初始空间,然后不够的时候在扩容。
销毁:
因为空间是malloc在堆区申请出来的,所以需要我们进行手动释放,防止内存泄露。

代码:

//初始化和最后销毁
void STInit(ST* ps)
{
	assert(ps);
	ps->a = (STDateType*)malloc(sizeof(ST) * 5);
	if (ps->a == NULL)
	{
		perror("malloc fail");
		return;
	}
	ps->top = 0;
	ps->capacity = 5;
}
void STDestory(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->capacity = 0;
	ps->a = NULL;
	1.没有让top也就是栈顶位置重置。
	ps->top = 0;
	//最后在Test.c上让结构体指针指向空。
}

3、入栈

入栈只能从栈顶入。

//入栈
void STPush(ST* ps, STDateType x)
{
	assert(ps);
	if (ps->top == ps->capacity) //判断是否满了
	{
		STDateType* temp = (STDateType*)realloc(ps->a, ps->capacity * sizeof(ST) * 2);
		if (temp == NULL)
		{
			perror("realloc fail");
			return;
		}
		else
		{
			ps->a = temp;
			ps->capacity *= 2;
			temp = NULL;
		}
	}
	ps->a[ps->top] = x;
	ps->top++;
}

4、出栈

直接减1就行。

//出栈
void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	ps->top--;
}

5、元素个数

就等于我们结构体里记录数据个数的值。

//元素个数
int STSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

6、判断是否为空

为什么这些简单的操作也要封装成函数呢?
因为编写函数的肯定是一个人,但是使用函数的人并不知道创建的具体是什么,比如结构体里的那个记录元素个数的,可能另一个人编写的时候该变量是记录栈顶下标的,那么就会总是比总个数小1,所以使用者并不能判断到底是哪个,所以需要编写函数的人把每个单独的功能都尽可能封装成函数,当使用者使用时,不需要区分那么多,直接调用对应函数,就能得到想要的结果。

代码:

//判断是否为空
bool STEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

7、栈顶元素

同上一个的描述,因为不知道记录的是栈顶元素的下标还是元素的总个数,所以为了方便且避免出错,需要封装成函数让使用者使用。

//栈顶元素
STDateType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	return ps->a[ps->top - 1];
}

三、总代码

Stack.h

`Stack.h

  #pragma once

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

typedef int STDateType;

typedef struct Stack
{
	STDateType* a;
	int top;//如果初始化为0,可以理解为元素个数(也就是栈顶元素下标+1),如果初始化为-1,可以理解为栈顶元素的下标
	int capacity;
}ST;

//初始化和最后销毁
void STInit(ST* ps);
void STDestory(ST* ps);

//入栈
void STPush(ST* ps, STDateType x);

//出栈
void STPop(ST* ps);

//元素个数
int STSize(ST* ps);

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

//栈顶元素
STDateType STTop(ST* ps);

Stack.c

Stack.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "Stack.h"

//初始化和最后销毁
void STInit(ST* ps)
{
	assert(ps);
	//ps->a = malloc(sizeof(ST) * 5);  1.没有强转
	ps->a = (STDateType*)malloc(sizeof(ST) * 5);
	2.开辟新空间后没有检查
	if (ps->a == NULL)
	{
		perror("malloc fail");
		return;
	}
	ps->top = 0;
	ps->capacity = 5;
}
void STDestory(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->capacity = 0;
	ps->a = NULL;
	1.没有让top也就是栈顶位置重置。
	ps->top = 0;
	//最后在Test.c上让结构体指针指向空。
}

//入栈
void STPush(ST* ps, STDateType x)
{
	assert(ps);
	//if (ps->top == ps->capacity)
	//{
	//	ST* str = realloc(ps->a, ps->capacity * sizeof(ST) * 2);
	//	if (str == NULL)
	//	{
	//		perror("realloc fail");
	//		return;
	//	}
	//}  
	1.没有把扩容的时候创建的新指针赋给原指针
	if (ps->top == ps->capacity) //判断是否满了
	{
		//ST* temp = realloc(ps->a, ps->capacity * sizeof(ST) * 2);
		//2.指针应该指向数据的类型的地址,而且realloc也没强转为数据类型的指针
		STDateType* temp = (STDateType*)realloc(ps->a, ps->capacity * sizeof(ST) * 2);
		if (temp == NULL)
		{
			perror("realloc fail");
			return;
		}
		else
		{
			ps->a = temp;
			3.忘记让结构体内的容量*2
			ps->capacity *= 2;
			temp = NULL;
		}
	}
	ps->a[ps->top] = x;
	ps->top++;
}

//出栈
void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	ps->top--;
}

//元素个数
int STSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

//判断是否为空
bool STEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

//栈顶元素
STDateType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));
	return ps->a[ps->top - 1];
}

Test.c

Test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "Stack.h"

int main()
{
	ST ps;
	STInit(&ps);
	STPush(&ps, 0);
	STPush(&ps, 1);
	STPush(&ps, 2);
	STPush(&ps, 3);
	STPush(&ps, 4);

	//打印,因为只能从栈顶出,所以每打印一个数据就需要弹出这个数据(出栈)。

	while (!STEmpty(&ps))
	{
		printf("%d ", STTop(&ps));
		STPop(&ps);//打印和出栈是一对,因为想要打印下一个,那么栈顶的元素必须出栈
	}
	STDestory(&ps);
	ps.a = NULL;
	return 0;
}

四、总结

在这里插入图片描述

✨请点击下面进入主页关注大魔王
如果感觉对你有用的话,就点我进入主页关注我吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/447776.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【半个月实践】普通人如何利用ChatGPT变现?(附镜像网站)

前言1.PPT2.百度问答3.代写文章4.设计LOGO 前言 如今ChatGPT的话题爆火各大平台&#xff0c;所谈论的方向也各不相同&#xff0c;或许是ChatGPT使用方法、应用领域、前景趋势等等。而这必然也产生了信息差&#xff0c;使得大多数人可以利用ChatGPT变现。   而在这一开始&…

嵌入式QT (使用 Qt Designer 开发)

一、使用 UI 设计器开发程序 1.1、 在 UI 文件添加一个按钮 1.2、在 UI 文件里连接信号与槽 所谓信号即是一个对象发出的信号&#xff0c;槽即是当这个对象发出这个信号时&#xff0c;对应连接的槽就发被执行或者触发。 UI 设计器里信号与槽的连接方法一&#xff1a; 在主窗…

分类预测 | MATLAB实现BO-CNN-LSTM贝叶斯优化卷积长短期记忆网络多输入分类预测

分类预测 | MATLAB实现BO-CNN-LSTM贝叶斯优化卷积长短期记忆网络多输入分类预测 目录 分类预测 | MATLAB实现BO-CNN-LSTM贝叶斯优化卷积长短期记忆网络多输入分类预测效果一览基本介绍模型搭建程序设计参考资料 效果一览 基本介绍 MATLAB实现BO-CNN-LSTM贝叶斯优化卷积长短期记…

TCP长连接的连接池、容量控制与心跳保活

一、长连接与短连接 TCP 本身并没有长短连接的区别&#xff0c;长短与否&#xff0c;完全取决于我们怎么用它。 短连接&#xff1a;每次通信时&#xff0c;创建 Socket;一次通信结束&#xff0c;调用 socket.close()。这就是一般意义上的短连接&#xff0c;短连接的好处是管理…

FastReport .NET 2023.2.7 FastReport Crack

快速报告 .NET 适用于 .NET 7 的报告和文档创建库 v. 2023.2.7 适用于 .NET 7、.NET Core、Blazor、ASP.NET、MVC 和 Windows Forms 的全功能报告库。它可以在微软视觉工作室 2022 和 JetBrains Rider 中使用。 利用 .NET 7、.NET Core、Blazor、ASP.NET、MVC 和 Windows For…

yara规则--编写

编写 YARA 规则 — yara 4.2.0 文档 YARA规则易于编写和理解&#xff0c;并且它们的语法是 类似于 C 语言。这是您可以编写的最简单的规则 YARA&#xff0c;它什么都不做&#xff1a; rule dummy {condition:false } 一、规则标识符 每个规则都以关键字“ rule”开头&#xff0…

成功案例丨Fortinet为跨国汽配制造企业打造典型安全SD-WAN网络

某国际化汽车配件制造企业&#xff08;以下简称某企业&#xff09;为解决跨国数据传输难、单一网络费用贵等痛点&#xff0c;决定采用SD-WAN这一新的组网形式。Fortinet携手中企通信为其打造组网高效、云网一体化、集中管理和编排的安全SD-WAN网络&#xff0c;通过精准流量和应…

数据库实验 | 第5关:使用游标的存储过程

任务描述 本关任务&#xff1a; jdxx数据表有四个字段&#xff0c;分别是省份(sf)、城市(cs)、区县(qxmc)、街道(name)。 例如&#xff0c;查询天心区(qxmc)的所有字段的值结果如图所示 任务要求 建立存储过程 tjdq(in sf varchar(10)) 输入省份的名称&#xff0c;将该省份…

创建web项目-----idea

创建项目 file—new—projiect java enterprise—next next 修改项目名字&#xff0c;finish 在此窗口打开新建的项目&#xff0c;选择this Window 新建好项目后是这样子的 配置项目的tomcat环境 file—project structure project 配置jdk和编译输入目录 libraries配…

【数据结构与算法】图像——四叉树自适应模糊(ppm图像为例)

源于大作业~~ 目录 前言 一、实现算法 二、结果展示 三、算法框架 (1) QuadTreeNode.h (2) 结点扩展、细化模糊层次 (3) 模糊化图像四叉树转为图像 (4) 主函数代码 四、说明 五、结语 前言 一张图片常常会存在空间冗余&#xff0c;即一大部分区域的色彩值相同&am…

Node.js二:fs模块

一.fs模块概述 2.fs异步写入 /*** 新建一个文件夹&#xff0c;座右铭.txt&#xff0c;写入内容三人行必有我师焉*///1.导入fs模块 const fs require(fs);//2.写入文件 fs.writeFile(./座右铭.txt,三人行必有我师焉,err >{//err写入失败&#xff1a;错误对象&#xff0c;写…

搭建CDH错误记录(踩坑无数)

搭建CDH流程记录 如何搭建本地yum源 1.配置yum源这里使用 阿里源 http://mirrors.aliyun.com/repo/Centos-7.repo wget http://mirrors.aliyun.com/repo/Centos-7.repo2.安装http软件 yum install httpd -y3.配置httpd.conf vi /etc/httpd/conf/httpd.conf在 AddType appli…

【社区图书馆】vue的生命周期

目录 vue的生命周期 生命周期流程 Init Events & Lifecycle beforeCreate Init injections & reactivity created beforeMount Create vm $el and replace ‘el’ with it mounted beforeUpdate Virtual Dom re-render and patch updated beforeDestroy vm…

python+vue 大学生社团管理系统

本系统分为学生&#xff0c;管理员&#xff0c;社团负责人三个角色&#xff0c;学生可以注册登陆系统&#xff0c;查看社团&#xff0c;申请入团&#xff0c;查看参加社团活动&#xff0c;查看社团新闻&#xff0c;社团负责人对社团信息&#xff0c;入团审核&#xff0c;社团新…

Opencv+Python笔记(五)图像阈值化处理

图像阈值化可以理解为一个简单的图像分割操作&#xff0c;阈值又称为临界值&#xff0c;它的目的是确定出一个范围&#xff0c;然后这个范围内的像素点使用同一种方法处理&#xff0c;而阈值之外的部分则使用另一种处理方法或保持原样。 阈值处理有2种方式&#xff0c;一种是固…

ijkplayer解码流程源码解读

ijkplayer是一款基于ffmpeg的在移动端比较流行的开源播放器。FFmpeg是一款用于多媒体处理、音视频编解码的自由软件工程&#xff0c;采用LGPL或GPL许可证。 要想理解ijkplayer源码&#xff0c;首先得知道视频播放器的基本原理。 视频播放器播放一个互联网上的视频文件&#xf…

win10怎么录屏幕视频带声音?有哪些需要注意的地方?

随着科技的不断发展&#xff0c;屏幕录制已成为常见的工具之一。在Win10系统中&#xff0c;录制屏幕视频带声音也变得越来越简单。本文将指导您如何在Win10上实现录制屏幕视频带声音&#xff0c;并介绍一些需要注意的地方。 需要用到的工具和步骤 在Win10系统中&#xff0c;自…

【u盘提示:驱动器未格式化】如何解决?

u盘虽然使用很方便&#xff0c;可随时拷贝资料到任何有电脑的地方&#xff0c;但它的问题也是比较多的&#xff0c;其中u盘提示驱动器未格式化故障最让人心虚&#xff0c;因为已经无法打开u盘了&#xff0c;里面的资料怎么办&#xff0c;很重要的怎么办&#xff0c;所以今天就教…

OAuth2.0 实战总结

title: OAuth2.0 实战总结 date: 2023-01-30 11:23:12 tags: OAuth2.0 categories:开发技术及框架 cover: https://cover.png feature: false 1. 引言 1.1 OAuth 2.0 是什么&#xff1f; 用一句话总结来说&#xff0c;OAuth 2.0 就是一种授权协议。那如何理解这里的“授权”…

前端调试技巧

前端工作中&#xff0c;不仅编码很重要&#xff0c;重现bug&#xff0c;解决bug的能力同样重要。而这些都离不开代码调试。本文就一些调试技巧做出总结&#xff0c;不足之处&#xff0c;欢迎大家多多补充。 PC调试 console.log() 在你觉得有问题的代码处&#xff0c;加上一句 …