数据结构:栈的创建、使用以及销毁

news2024/10/25 21:26:47

这里写目录标题

  • 栈的结构与概念
  • 栈底层结构的选取
  • 栈的代码实现(stack)
    • 头文件(stack.h)
    • 栈的初始化
    • 栈的销毁
    • 入栈
    • 出栈
    • 获取栈顶数据
    • 获取栈大小
    • 代码的测试

栈的结构与概念

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

栈底层结构的选取

数组:
入栈的时间复杂度:O(1)
出栈的时间复杂度:O(1)
单链表:
入栈需要找到最后一个节点,所以要遍历单链表,时间复杂度:O(N)
出栈跟入栈一样,也需要遍历寻找最后一个节点,时间复杂度:O(N)
双向链表:
入栈可以通过哨兵位来找到最后一个节点,时间复杂度:O(1)
出栈的话同理,时间复杂度:O(1)

这样的话就很明显了,数组跟双向链表时比较合适的。
但是因为涉及电脑的缓存问题,所以我们最后还是选择了数组。
电脑数据缓存:就是电脑在访问内存时会缓存连续的空间,这样我们就不用频繁的来访问内存,但是链表的物理逻辑是不一定满足连续空间的,所以相比下来数组就会更好一些,因为对缓存这方面了解较少,所以就不做太多介绍,有兴趣可以去问问度娘哈。

栈的代码实现(stack)

头文件(stack.h)

以下是我们本次要编写的一些函数代码:

#pragma once

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

typedef int STDataType;
typedef struct Stack
{
	STDataType* st;//数组
	int top;//栈顶
	int capacity;//栈大小
}ST;

void STInit(ST* ps);//栈的初始化

void STDestroy(ST* ps);//栈销毁

void StackPush(ST* ps, STDataType x);//入栈

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

STDataType StackTop(ST* ps);//获取栈顶数据

int STSize(ST* ps);//获取栈的大小

栈的初始化

思路:
给结构体赋一些初值,让指针指向NULL,刚开始还没有数据,所以栈顶以及栈的有效数据都为0。
代码:

void STInit(ST* ps)
{
	assert(ps);
	ps->st = NULL;
	ps->capacity = ps->top = 0;
}

栈的销毁

思路:
因为我们经常会入栈出栈,所以空间是不定的,所以我们就会用realloc来创建连续空间(realloc函数不了解的可以自行了解一下哈,之前已经介绍过了),当我们销毁时就是用free函数释放该空间,然后让结构体成员赋初值即可。
代码:

void STDestroy(ST* ps)
{
	assert(ps);
	if(ps->st)//判断指针是否位NULL
		free(ps->st);
	ps->st = NULL;
	ps->top = ps->capacity = 0;
}

入栈

思路:
因为我们有个top是指向栈顶的,当我们初始化后,top位0,这个时候我们入栈就直接将数据放入top指向的位置即可,当入栈完后,我们将top++,一直让他指向栈顶的位置。

入栈的空间管理:
因为我们是动态申请空间,所以避免不了数组空间不够的情况。
我们使用三目操作符判断数据空间大小capacity,
当capacity为0,我们就给他赋值为4,当不为0,我们就申请二倍的动态空间。

代码:

void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		ps->capacity = ps->capacity == 0 ? 4 : 2 * (ps->capacity);
		STDataType* tmp = (STDataType*)realloc(ps->st, sizeof(int) * ps->capacity);//创建临时指针来暂存新空间地址,防止开辟失败导致原数据丢失
		if (tmp == NULL)
		{
			perror("relloc fail!\n");
			exit(1);
		}
		ps->st = tmp;
	}
	ps->st[ps->top++] = x;
}

出栈

思路:
结构体的top是一直指向栈顶,我们只需要将指向栈顶的这个数据向下挪动一位就可以了。
但是这里要注意,当栈为NULL时,就不能再出栈了。

//空栈,就是跟初始化结束状态相似,top一定是为0,栈大小不一定为0,
//因为我们一直出栈直到数据清空的话,栈就为空栈,但是出栈时我们不会修改栈空间大小
bool STEmpty(ST* ps)
{
	assert(ps);
	return ps->top != 0;
}
void StackPop(ST* ps)
{
	assert(ps);
	assert(STEmpty(ps));//判断是否为空栈
	--ps->top;
}

获取栈顶数据

思路:
top是一直指向新栈顶的,我们要获取栈顶的数据就是获取top-1的数据。
具体如图:
在这里插入图片描述

代码:

STDataType StackTop(ST* ps)
{
	assert(ps);
	assert(STEmpty(ps));

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

获取栈大小

思路:
就是获取结构体capacity的值。

代码:

int STSize(ST* ps)
{
	assert(ps);
	return ps->capacity;
}

当然获取有效数据个数也很简单,就是返回top的值。

代码的测试

#define _CRT_SECURE_NO_WARNINGS 1

#include"stack.h"

void test()
{
	ST s;
	STInit(&s);
	StackPush(&s,1);
	StackPush(&s, 2);
	StackPush(&s, 3);
	StackPush(&s, 4);
	StackPush(&s, 4);
	

	while (s.top)
	{
		int tmp=StackTop(&s);
		printf("%d ", tmp);
		StackPop(&s);
	}
	STDestroy(&s);

}

int main()
{
	test();
	return 0;
}

入栈出栈:
在这里插入图片描述
销毁:
在这里插入图片描述
----------------------------------------------------------------分隔符
感谢观看,制作不易,看官老爷们给个三连吧,谢谢!

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

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

相关文章

【算法篇】动态规划类(1)(笔记)

目录 一、理论基础 1. 大纲 2. 动态规划的解题步骤 二、LeetCode 题目 1. 斐波那契数 2. 爬楼梯 3. 使用最小花费爬楼梯 4. 不同路径 5. 不同路径 II 6. 整数拆分 7. 不同的二叉搜索树 一、理论基础 1. 大纲 动态规划&#xff0c;英文&#xff1a;Dynamic Programm…

企业水、电、气、热等能耗数据采集系统

介绍 通过物联网技术&#xff0c;采集企业水、电、气、热等能耗数据&#xff0c;帮企业建立能源管理体系&#xff0c;找到跑冒滴漏&#xff0c;从而为企业节能提供依据。 进一步为企业实现碳跟踪、碳盘查、碳交易、谈汇报的全生命过程。 为中国碳达峰-碳中和做出贡献。 针对客…

【C++进阶】set的使用

1. 序列式容器和关联式容器 前面&#xff0c;我们已经接触过STL中的部分容器如&#xff1a;string、vector、list、deque、array、forward_list等&#xff0c;这些容器统称为序列式容器&#xff0c;因为逻辑结构为线性序列的数据结构&#xff0c;两个位置存储的值之间⼀般没有紧…

【工具箱】Flash基础及“SD NAND Flash”的测试例程

目录 一、“FLASH闪存”是什么&#xff1f; 1. 简介 2. 分类 3. 性能 4.可靠性 5.易用性 二、SD NAND Flash 1. 概述 2. 特点 3. 引脚分配 4. 数据传输模式 5. SD NAND寄存器 6. 通电图 7. 参考设计 三、STM32测试例程 1. 初始化 2. 单数据块测试 3. 多数据块…

场景题 - 画三角形并只点击三角形触发事件

简介 画一个三角形并仅点击三角形区域才会触发点击事件。 可以拆解成&#xff1a; 画个三角形绑定点击事件&#xff08;涉及点击区域&#xff09; 这里提供更多更好用的方法&#xff0c;svg polygon绘制三角形、canvas、css clip-path:polygon( ) 裁剪可视区域&#xff0c;并…

文件和目录的权限管理

定义&#xff1a; 文件和目录的权限管理在操作系统中至关重要&#xff0c;特别是在多用户环境下&#xff0c;它决定了不同用户对文件和目录的访问和操作权限。 一、基本权限类型及表示方法 在Linux系统中&#xff0c;文件和目录的权限分为三类&#xff1a;读取权限&#xff08;…

谷歌-BERT-第一步:模型下载

1 需求 需求1&#xff1a;基于transformers库实现自动从Hugging Face下载模型 需求2&#xff1a;基于huggingface-hub库实现自动从Hugging Face下载模型 需求3&#xff1a;手动从Hugging Face下载模型 2 接口 3.1 需求1 示例一&#xff1a;下载到默认目录 from transform…

南邮-软件安全--第一次实验报告-非爆破计算校验值

软件安全第一次实验报告&#xff0c;切勿直接搬运&#xff08;改改再交&#xff09; 实验要求 1、逆向分析目标程序运行过程&#xff0c;找到程序的关键校验点&#xff1b; 2、以非爆破的方式正确计算crackme的校验值&#xff1b; 内容 使用x32dbg对文件进行分析 打开文件…

思迈特:在AI时代韧性增长的流量密码

作者 | 曾响铃 文 | 响铃说 “超级人工智能将在‘几千天内’降临。” 最近&#xff0c;OpenAI 公司 CEO 山姆奥特曼在社交媒体罕见发表长文&#xff0c;预言了这一点。之前&#xff0c;很多专家预测超级人工智能将在五年内到来&#xff0c;奥特曼的预期&#xff0c;可能让这…

构建可扩展的高校学科竞赛平台:SpringBoot案例分析

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

高效管理学科竞赛:SpringBoot平台的创新应用

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理高校学科竞赛平台的相关信息成为必然。开发…

Zookeeper快速入门:部署服务、基本概念与操作

文章目录 一、部署服务1.下载与安装2.查看并修改配置文件3.启动 二、基本概念与操作1.节点类型特性总结使用场景示例查看节点查看节点数据 2.文件系统层次结构3.watcher 一、部署服务 1.下载与安装 下载&#xff1a; 一定要下载编译后的文件&#xff0c;后缀为bin.tar.gz w…

算法:525.连续数组

题目 链接&#xff1a;leetcode 思路分析&#xff08;前缀和&#xff09; 首先介绍一个小技巧 在处理二进制数组的时候&#xff0c;因为数组里面只有0和1&#xff0c;我们可以将所有的0变成-1 这个时候1和-1之间就可以产生很多抵消&#xff0c;有利于处理数组。 在该题中&am…

2.2.1 绘制Canvas路径 - 绘制线条

文章目录 1. 绘制线条2. 绘制具有不同结束线帽的线条3. 绘制向阳花图形 今天我们要一起探讨的是如何使用HTML5的Canvas元素来绘制各种图形。Canvas提供了一个强大的图形绘制API&#xff0c;使我们能够在网页上绘制出各种复杂的图形和动画。接下来&#xff0c;我将通过几个实战示…

从Naive RAG到Agentic RAG:基于Milvus构建Agentic RAG

检索增强生成&#xff08;Retrieval-Augmented Generation, RAG&#xff09;作为应用大模型落地的方案之一&#xff0c;通过让 LLM 获取上下文最新数据来解决 LLM 的局限性。典型的应用案例是基于公司特定的文档和知识库开发的聊天机器人&#xff0c;为公司内部人员快速检索内部…

如何在数仓中处理缓慢变化维度(SCD)

在数据仓库中&#xff0c;处理缓慢变化维度&#xff08;SCD&#xff0c;Slowly Changing Dimension&#xff09;是一个非常常见且重要的问题。为了保证数据的完整性和准确性&#xff0c;我们通常会采取不同的策略来处理维度表中的数据变化。SCD的核心解决方案是通过不同类型的历…

Run the FPGA VI 选项的作用

Run the FPGA VI 选项的作用是决定当主机 VI 运行时&#xff0c;FPGA VI 是否会自动运行。 具体作用&#xff1a; 勾选 “Run the FPGA VI”&#xff1a; 当主机 VI 执行时&#xff0c;如果 FPGA VI 没有正在运行&#xff0c;系统将自动启动并运行该 FPGA VI。 这可以确保 FPG…

使用Hugging Face中的BERT进行标题分类

使用Hugging Face中的BERT进行标题分类 前言相关介绍出处基本原理优点缺点 前提条件实验环境BERT进行标题分类准备数据集读取数据集划分数据集设置相关参数创建自己DataSet对象计算准确率定义预训练模型定义优化器训练模型保存模型测试模型 参考文献 前言 由于本人水平有限&…

视频文案提取

视频文案提取 通义听悟 &#x1f3c6;优点 自动提取音视频关键词、总结、提炼视频大纲、中英双字幕可以识别不同声音进行文案区分&#xff0c;还支持直接AI改写提取的文案旁边还有AI助手帮助你回答问题和对知识举一反三相关视频介绍&#x1f449;原地封神&#xff01;录音、…

拆解学习【反激-PD-氮化镓】(一)

小米67W桌面快充插座&#xff1a; 反激基本拓扑&#xff1a; 商用场景下&#xff0c;这个拓扑进行了如下优化&#xff1a; 1.Q22换成了氮化镓开关管&#xff0c;当然需要适配的能驱动氮化镓的控制芯片 2.D21二极管换成了MOS管。 3.由于是AC220V输入&#xff0c;设计了整流桥…