(超详细)数据结构——“栈”的深度解析

前言:

   在前几章我们介绍了线性表的基本概念,也讲解了包括顺序表,单链表,双向链表等线性表,相信大家已经对线性表比较熟悉了,今天我们要实现线性表的另一种结构——栈。

1.栈的概念

    栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFOLast In First Out)的原则。这里的栈与内存中的栈在结构上是一致的,它们提取数据和存放数据也叫出栈和压栈。

压栈:栈的插入操作叫做进栈 / 压栈 / 入栈, 入数据在栈顶
出栈:栈的删除操作叫做出栈。 出数据也在栈顶

2.栈的实现 

   栈的实现可以选择使用链表或者数组,这两种结构都可以很好的实现栈的各种操作,相对而言,数组是更好的选择,因为栈的插入只需要对结构进行尾插,而数组尾插的代价相较于链表来说没有那么大。

3.代码实现 

   为了方便管理,我们将栈的实现分为三个文件,分别是test.c ,Stack.c ,Stack.h(stack中译为堆叠,也就是栈的意思) ,由于我们选择使用数组来实现栈,所以在数据结构中我们就使用动态顺序表,顺序表中要包含顺序表空间大小,一个指向这块空间的指针和top来表示栈顶,而这个数据的类型是视情况而定的,我们使用typedef对数组中的元素类型改名,使栈存储的数据类型更加灵活,为了方便使用,我们也将栈类型改名为ST:

typedef int STDataType;
typedef struct Stack
{
	STDataType* arr;
	int top;
	int capacity;//表示当前空间大小

}ST;

实现了栈的基本结构之后,我们接下来要实现栈的各种操作,例如栈的压栈和出栈等操作。

3.1 栈的初始化 

   在程序刚开始执行使,栈内部的所有成员都没有初始化,它们的值都是不确定的,而不确定意味着不可控,我们后续需要通过这些成员的值来判断执行一些操作,例如表示数组的空间大小capacity变量,如果它的值是不确定的,那么我们也无法对数组执行有效操作,所以我们要对它进行初始化,而刚开始栈是空的,所以我们让指向栈的指针指向空,元素为0个:

void STInit(ST* pst)
{
	assert(pst);
	pst->arr = NULL;
	pst->capacity = 0;
	pst->top = 0;
}//初始化

3.2 栈的销毁

   我们栈的空间使用的的是顺序表结构实现的,而顺序表的空间都是在堆上开辟的,所以我们需要手动将这些空间释放:

void STDestroy(ST* pst)
{
	assert(pst);

	free(pst->arr);
	pst->arr = NULL;
	pst->capacity = pst->top = 0;
}//销毁

3.3 压栈操作 

   压栈就是进栈的意思,对栈进行压栈操作之前,我们要判断栈空间够不够,如果不够,我们需要手动从堆上开辟一块空间,而一次开辟的空间是有限的,将空间开辟得太大也会造成空间浪费,所以我们判断在空间不够时使用realloc函数重新开辟一块更大的空间,而插入操作则比较简单,只需要在数组中top指向的位置将我们要插入的数据插入,再让top加一就可以了:

void STPush(ST* pst, STDataType x)
{
	assert(pst);
	if (pst->capacity == pst->top)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* ret = (STDataType*)realloc(pst->arr, newcapacity * sizeof(STDataType));
		if (ret == NULL)
		{
			perror("realloc fail");
			return;
		}
		pst->capacity = newcapacity;
		pst->arr = ret;
	}
	pst->arr[pst->top++] = x;
}//压栈

3.4 出栈操作 

    出栈操作也就是删除栈顶的元素,这个操作比较简单,只需要让top减一,因为我们在取数据时,只取top下面的数据,top上面的数据则默认不在栈内,这样就相当于我们将这个元素删除了:

void STPop(ST* pst)
{
	assert(pst);
	pst->top--;
}//删除

3.5 栈顶 

 有时我们频繁对栈进行插入和删除操作,我们需要查看栈顶情况,就可以使用这个方法,,这个方法的实现也相对简单,只需要返回栈中top下标的下一个 元素,因为top始终指向栈顶元素的下一个位置,我们插入元素也是先将元素放到下标为top的位置中,再让top加一:

STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
	return pst->arr[pst->top - 1];
}//栈顶

3.6 判空 

  我们有时要对栈进行置空操作,如果不确定栈何时为空就可以使用这个方法,判空操作只需要判断top是否为0就可以了,如果为零,就为真,返回true,如果不为空,就为假返回false:

bool STEmpty(ST* pst)
{
	assert(pst);
	return pst->top == 0;
}//判空

3.7 栈的大小 

   我们前面提到了,top就是栈的大小,如果我们直接查看top不是更快吗,为什么要单独写一个方法呢,事实上我们单独实现一个方法是为了方便统一操作,要执行何种操作,只需要调用一个方法就可以实现:

int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}//大小

3.8 测试

实现完这些方法之后,我们要测试一下我们的代码有没有问题:

经过我们测试,这些方法都没有问题,本期栈的讲解到这就结束了,是不是比前几期简单一些呢,我们亲自上手就知道了,代码放在下面感兴趣的小伙伴们可以试试哦。 

Stack.h :

#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* pst);//初始化

void STDestroy(ST* pst);//销毁

void STPush(ST* pst, STDataType x);//压栈

void STPop(ST* pst);//删除

STDataType STTop(ST* pst);//栈顶元素

bool STEmpty(ST* pst);//判空

int STSize(ST* pst);//大小

Stack.c :

#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"

void STInit(ST* pst)
{
	assert(pst);
	pst->arr = NULL;
	pst->capacity = 0;
	pst->top = 0;
}//初始化

void STPush(ST* pst, STDataType x)
{
	assert(pst);
	if (pst->capacity == pst->top)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* ret = (STDataType*)realloc(pst->arr, newcapacity * sizeof(STDataType));
		if (ret == NULL)
		{
			perror("realloc fail");
			return;
		}
		pst->capacity = newcapacity;
		pst->arr = ret;
	}
	pst->arr[pst->top++] = x;
}//压栈

void STPop(ST* pst)
{
	assert(pst);
	pst->top--;
}//删除

STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
	return pst->arr[pst->top - 1];
}//栈顶

bool STEmpty(ST* pst)
{
	assert(pst);
	return pst->top == 0;
}//判空

int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}//大小

void STDestroy(ST* pst)
{
	assert(pst);

	free(pst->arr);
	pst->arr = NULL;
	pst->capacity = pst->top = 0;
}//销毁

test.c :

#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"
void test()
{
	ST s;

	STInit(&s);
	printf("插入四个元素\n");
	STPush(&s, 1);
	STPush(&s, 2);
	STPush(&s, 3);
	STPush(&s, 4);
	
	printf("栈顶元素为:%d\n", STTop(&s));
	printf("%d个元素\n", STSize(&s));
	while (!STEmpty(&s))
	{
		printf("%d ", STTop(&s));
		STPop(&s);

	}
	STDestroy(&s);
}

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

 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

熊猫烧香是什么?

熊猫烧香&#xff08;Worm.WhBoy.cw&#xff09;是一种由李俊制作的电脑病毒&#xff0c;于2006年底至2007年初在互联网上大规模爆发。这个病毒因其感染后的系统可执行文件图标会变成熊猫举着三根香的模样而得名。熊猫烧香病毒具有自动传播、自动感染硬盘的能力&#xff0c;以及…

动手学深度学习(Pytorch版)代码实践 -计算机视觉-39实战Kaggle比赛:狗的品种识别(ImageNet Dogs)

39实战Kaggle比赛&#xff1a;狗的品种识别&#xff08;ImageNet Dogs&#xff09; 比赛链接&#xff1a;Dog Breed Identification | Kaggle 1.导入包 import torch from torch import nn import collections import math import os import shutil import torchvision from…

x-file-storage一行代码进行文件上传,摆脱阿里云,腾讯云,华为云等不同云的学习,简单高效

问题&#xff1a; 不使用x-file-storage时如果使用某个云首先需要学习他的sdk,这样很麻烦&#xff0c;而x-file-storage集成了各种云的上传&#xff0c;只需要进行配置即可一行代码进行上传 使用 官方地址&#xff1a;X File Storage 一行代码将文件存储到本地、FTP、SFTP、…

【小沐学AI】Python实现语音识别(whisperX)

文章目录 1、简介1.1 whisper1.2 whisperX 2、安装2.1 安装cuda2.2 安装whisperX 结语 1、简介 1.1 whisper https://arxiv.org/pdf/2212.04356 https://github.com/openai/whisper Whisper 是一种通用语音识别模型。它是在各种音频的大型数据集上训练的&#xff0c;也是一个…

时间复杂度计算

要求算法的时间复杂度时&#xff0c;我们可以分析给定表达式 的阶。让我们来逐步分析&#xff1a; 分析阶的定义&#xff1a; 当我们说一个表达式的时间复杂度是 ( O(g(n)) )&#xff0c;我们指的是当 ( n ) 趋近无穷大时&#xff0c;表达式的增长率与 ( g(n) ) 的增长率相似。…

两数之和你会,三数之和你也会吗?o_O

前言 多少人梦想开始的地方&#xff0c;两数之和。 但是今天要聊的不是入门第一题&#xff0c;也没有面试官会考这一题吧…不会真有吧&#xff1f; 咳咳不管有没有&#xff0c;今天的猪脚是它的兄弟&#xff0c;三数之和&#xff0c;作为双指针经典题目之一&#xff0c;也是常…

SolidWorks强大的工程设计软件下载安装,实现更为高效的设计流程

结构分析&#xff1a;SolidWorks作为一款强大的工程设计软件&#xff0c;集成了有限元分析&#xff08;FEA&#xff09;工具&#xff0c;这一工具的运用在工程设计领域具有举足轻重的地位。FEA工具在SolidWorks中的集成&#xff0c;使得工程师们能够便捷地对零件和装配体进行精…

第三十八篇——复盘:如何把信息论学以致用?

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 信息论是一个好的学科&#xff0c;里面穿插的知识符合这个时代我们应该具…

STM32F1+HAL库+FreeTOTS学习2——STM32移植FreeRTOS

STM32F1HAL库FreeTOTS学习2——STM32移植FreeRTOS 获取FreeRTOS源码创建工程窥探源码移植 上期我们认识了FreeRTOS&#xff0c;对FreeRTOS有了个初步的认识&#xff0c;这一期我们来上手移植FreeRTOS到STM32上。 获取FreeRTOS源码 进入官网&#xff1a;https://www.freertos.o…

vue+go实现web端连接Linux终端

vuego实现web端连接Linux终端 实现效果 实现逻辑1——vue 依赖包 "xterm": "^5.3.0","xterm-addon-attach": "^0.9.0","xterm-addon-fit": "^0.8.0"样式和代码逻辑 <template><a-modalv-model:visib…

短视频矩阵系统:打造品牌影响力的新方式

一、短视频矩阵概念 短视频营销革命&#xff1a;一站式解决策略&#xff01;短视频矩阵系统是一款专为企业营销设计的高效工具&#xff0c;旨在通过整合和优化众多短视频平台资源&#xff0c;为企业呈现一个全面的短视频营销策略。该系统致力于协助企业以迅速且高效的方式制作…

【ARM】MCU和SOC的区别

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 了解SOC芯片和MCU芯片的区别 2、 问题场景 用于了解SOC芯片和MCU芯片的区别&#xff0c;内部结构上的区别。 3、软硬件环境 1&#xff09;、软件版本&#xff1a;无 2&#xff09;、电脑环境&#xff1a;无 3&am…

MySQL高级-MVCC-原理分析(RC级别)

文章目录 1、RC隔离级别下&#xff0c;在事务中每一次执行快照读时生成ReadView2、先来看第一次快照读具体的读取过程&#xff1a;3、再来看第二次快照读具体的读取过程: 1、RC隔离级别下&#xff0c;在事务中每一次执行快照读时生成ReadView 我们就来分析事务5中&#xff0c;两…

java第三十课 —— 面向对象练习题

面向对象编程练习题 第一题 定义一个 Person 类 {name, age, job}&#xff0c;初始化 Person 对象数组&#xff0c;有 3 个 person 对象&#xff0c;并按照 age 从大到小进行排序&#xff0c;提示&#xff0c;使用冒泡排序。 package com.hspedu.homework;import java.util.…

LLM——10个大型语言模型(LLM)常见面试题以及答案解析

今天我们来总结以下大型语言模型面试中常问的问题 1、哪种技术有助于减轻基于提示的学习中的偏见? A.微调 Fine-tuning B.数据增强 Data augmentation C.提示校准 Prompt calibration D.梯度裁剪 Gradient clipping 答案:C 提示校准包括调整提示&#xff0c;尽量减少产生…

数据结构与算法笔记:实战篇 - 剖析Redis常用数据类型对应的数据结构

概述 从本章开始&#xff0c;就进入实战篇的部分。这部分主要通过一些开源醒目、经典系统&#xff0c;真枪实弹地教你&#xff0c;如何将数据结构和算法应用到项目中。所以这部分的内容&#xff0c;更多的是知识点的回顾&#xff0c;相对于基础篇和高级篇&#xff0c;其实这部…

【Web3项目案例】Ethers.js极简入门+实战案例:实现ERC20协议代币查询、交易

苏泽 大家好 这里是苏泽 一个钟爱区块链技术的后端开发者 本篇专栏 ←持续记录本人自学智能合约学习笔记和经验总结 如果喜欢拜托三连支持~ 目录 简介 前景科普-ERC20 Ethers极简入门教程&#xff1a;HelloVitalik&#xff08;非小白可跳&#xff09; 教程概览 开发工具 V…

虚拟机配置与windows之间文件夹共享samba服务:

虚拟机配置与windows之间文件夹共享samba服务: #输入安装命令&#xff1a; 第一步: 下载samba cd /etc/ sudo apt-get install samba第二步: 配置用户 sudo smbpasswd -a 虚拟机用户名第三步: 进入配置文件配置共享文件 sudo vim /etc/samba/smb.conf末尾输入以下内容: [s…

全球最大智能立体书库|北京:3万货位,715万册,自动出库、分拣、搬运

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 北京城市图书馆的立体书库采用了先进的WMS&#xff08;仓库管理系统&#xff09;和WCS&#xff08;仓库控制系统&#xff09;&#xff0c;与图书…

代码随想录-二叉搜索树(1)

目录 二叉搜索树的定义 700. 二叉搜索树中的搜索 题目描述&#xff1a; 输入输出示例&#xff1a; 思路和想法&#xff1a; 98. 验证二叉搜索树 题目描述&#xff1a; 输入输出示例&#xff1a; 思路和想法&#xff1a; 530. 二叉搜索树的最小绝对差 题目描述&#x…