栈的实现详解

news2024/11/27 13:30:53

目录

  • 1. 栈
    • 1.1 栈的概念及结构
    • 1.2 栈的实现方式
    • 1.3 栈的应用场景
  • 2. 栈的实现
    • 2.1 结构体
    • 2.2 初始化
    • 2.3 销毁
    • 2.4 入栈
    • 2.5 出栈
    • 2.6 获取栈顶元素
    • 2.7 判空
    • 2.8 获取个数
  • 3. test主函数
  • 4. Stack.c文件
  • 5. Stack.h文件
  • 6. 运行展示

1. 栈

1.1 栈的概念及结构

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

在这里插入图片描述

在这里插入图片描述

1.2 栈的实现方式

栈可以通过多种方式实现,包括数组和链表等。使用数组实现的栈具有连续的内存空间,操作效率较高;而使用链表实现的栈则更加灵活,可以在动态环境中调整栈的大小。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
实现用的是数据栈。

1.3 栈的应用场景

函数调用:在计算机程序中,函数调用和返回的过程可以用栈来实现。当调用一个函数时,会将函数的返回地址和参数压入栈中;当函数返回时,会从栈中弹出这些信息,并返回到调用点继续执行。
浏览器的前进与后退:在浏览器中,可以使用两个栈来实现前进和后退功能。一个栈记录新访问的页面,另一个栈记录后退弹出的页面。当用户点击前进按钮时,从记录新访问页面的栈中弹出页面;当用户点击后退按钮时,从记录后退页面的栈中弹出页面。
表达式求值:在编译器中,可以使用栈来进行表达式的求值。将运算符和操作数压入栈中,并根据运算符的优先级和结合性进行出栈和计算操作,最终得到表达式的值。

2. 栈的实现

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。

在这里插入图片描述

在这里插入图片描述

2.1 结构体

首先要先把结构体定义出来,一个是数组栈,一个是指向栈顶元素的下一个,还有一个是增容。

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;//指向栈顶元素的下一个
	int capaicty;
}ST;

2.2 初始化

top等于0指向栈顶元素的下一个位置,top等于-1指向栈顶元素

//初始化
void STInit(ST* pst)
{
	assert(pst);

	pst->a = NULL;
	//pst->top = -1;//指向栈顶元素
	pst->top = 0;//指向栈顶元素的下一个位置
	pst->capaicty = 0;
}

2.3 销毁

防止造成野指针的错误

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

	pst->a = NULL;
	pst->top = 0;
	pst->capaicty = 0;
	free(pst->a);
}

2.4 入栈

先判断容量是否够,再实现动态增容。

//入栈
void STPush(ST* pst, STDataType x)
{
	//扩容
	if (pst->top == pst->capaicty)
	{
		int newCapaicty = pst->capaicty = 0 ? 4 : pst->capaicty * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, newCapaicty * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("STPush");
			return;
		}

		pst->a = tmp;
		pst->capaicty = newCapaicty;
	}

	pst->a[pst->top] = x;
	pst->top++;
}

2.5 出栈

看栈是否空,不是空就不能删,再top减减就行

//出栈
void STPpo(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));

	pst->top--;
}

2.6 获取栈顶元素

因为top指向栈顶元素的下一个,所以top要减1,当然空的时候也要判断一下

//获取栈顶元素
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));

	return pst->a[pst->top - 1];
}

2.7 判空

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

	return pst->top == 0;
}

2.8 获取个数

打印之前可以看还有多少个在栈中

//获取个数
int STsize(ST* pst)
{
	assert(pst);

	return pst->top;
}

3. test主函数

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include "Stack.h"

void TestStack1()
{
	ST st;
	STInit(&st);
	STPush(&st, 1);
	STPush(&st, 2);
	printf("%d ", STTop(&st));
	STPpo(&st);
	STPush(&st, 3);
	STPush(&st, 4);
	printf("size: %d\n", STsize(&st));
	
	//打印
	while (!STEmpty(&st))
	{
		printf("%d ", STTop(&st));
		STPpo(&st);
	}

	STDestroy(&st);
}

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

4. Stack.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include "Stack.h"


//初始化
void STInit(ST* pst)
{
	assert(pst);

	pst->a = NULL;
	//pst->top = -1;//指向栈顶元素
	pst->top = 0;//指向栈顶元素的下一个位置
	pst->capaicty = 0;
}

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

	pst->a = NULL;
	pst->top = 0;
	pst->capaicty = 0;
	free(pst->a);
}

//入栈
void STPush(ST* pst, STDataType x)
{
	//扩容
	if (pst->top == pst->capaicty)
	{
		int newCapaicty = pst->capaicty = 0 ? 4 : pst->capaicty * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, newCapaicty * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("STPush");
			return;
		}

		pst->a = tmp;
		pst->capaicty = newCapaicty;
	}

	pst->a[pst->top] = x;
	pst->top++;
}

//出栈
void STPpo(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));

	pst->top--;
}

//获取栈顶元素
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));

	return pst->a[pst->top - 1];
}

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

	return pst->top == 0;
}

//获取个数
int STsize(ST* pst)
{
	assert(pst);

	return pst->top;
}

5. Stack.h文件

#pragma once
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;//指向栈顶元素的下一个
	int capaicty;
}ST;

//初始化
void STInit(ST* pst);

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

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

//出栈
void STPpo(ST* pst);

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

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

//获取个数
int STsize(ST* pst);

6. 运行展示

在这里插入图片描述

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

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

相关文章

找不到dll文件如何修复,总结多种dll丢失的修复方法

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“缺少DLL文件”。那么&#xff0c;DLL到底是什么呢&#xff1f;为什么计算机会缺失DLL文件&#xff1f;缺失DLL文件会对电脑产生什么具体影响&#xff1f;本文将详细解析这些问题&#xff0…

UC Berkeley简介以及和Stanford的区别与联系

UC Berkeley Source: Google Map 中文版 UC Berkeley&#xff0c;全称University of California, Berkeley&#xff0c;是一所位于美国加利福尼亚州伯克利市的世界知名公立研究型大学。以下是关于UC Berkeley的详细介绍&#xff1a; 学术声誉和排名 学术声誉&#xff1a; U…

Android入门第69天-AndroidStudio中的Gradle使用国内镜像最强教程

背景 AndroidStudio默认连接的是dl.google的gadle仓库。 每次重新build时: 下载速度慢;等待了半天总时build faild;build到一半connection timeout;即使使用了魔法也难以一次build好;这严重影响了我们的学习、开发效率。 当前网络上的使用国内镜像的教程不全 网上的教程…

056、PyCharm 快速代码重构的方法

在实际的编程过程中&#xff0c;如果有一段代码需要在多个地方重复使用&#xff0c;我们应该将这段代码封装成一个函数。这样可以提高代码的可重用性和可维护性。 在PyCharm编辑器里&#xff0c;可以使用以下操作对代码块进行快速的重构。 &#xff08;1&#xff09;、选中一…

【数据分析】推断统计学及Python实现

各位大佬好 &#xff0c;这里是阿川的博客&#xff0c;祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 Python 初阶 Python–语言基础与由来介绍 Python–…

Spring Boot整合Redis通过Zset数据类型+定时任务实现延迟队列

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

mac终端:定位于当前文件夹位置Terminal设置快捷键,实现快速启动--m系列

mac自动脚本(f3直接搜或者找其他->自动操作) 然后找到如下功能: 代码如下: on run {input, parameters} tell application "Finder" set currFolder to POSIX path of (folder of the front window as string) end tell tell application "Termina…

人大高瓴/腾讯提出QAGCF:用于QA推荐的图形协同过滤

【摘要】问答(Q&A)平台通常推荐问答对来满足用户的知识获取需求,这与仅推荐单个项目的传统推荐不同。这使得用户行为更加复杂,并为Q&A推荐带来了两个挑战,包括:协作信息纠缠,即用户反馈受问题或答案的影响;以及语义信息纠缠,其中问题与其相应的答案相关联,不同问答对之…

软件工程实务:软件产品

目录 1、软件产品的基本概念 2、软件工程是什么&#xff1f; 为什么产生软件工程? 软件工程是做什么的? 3、定制软件和软件产品的工程比较 4 、软件产品的运行模式 5、软件产品开发时需要考虑的两个基本技术因素 6、产品愿景 7、软件产品管理 8、产品原型设计 9、小结…

C/C++:指针用法详解

C/C&#xff1a;指针 指针概念 指针变量也是一个变量 指针存放的内容是一个地址&#xff0c;该地址指向一块内存空间 指针是一种数据类型 指针变量定义 内存最小单位&#xff1a;BYTE字节&#xff08;比特&#xff09; 对于内存&#xff0c;每个BYTE都有一个唯一不同的编号…

DeepSORT(目标跟踪算法)卡尔曼滤波中的贝叶斯定理

DeepSORT&#xff08;目标跟踪算法&#xff09;卡尔曼滤波中的贝叶斯定理 flyfish 从例子中介绍名词 假设我们有一个袋子&#xff0c;里面有5个红球和3个蓝球。我们从袋子里随机抽取一个球。 概率 (Probability) 我们想计算从袋子里抽到红球的概率 P ( R ) P(R) P(R)。 …

4D毫米波雷达技术及发展

文章目录 前言一、4D毫米波雷达是什么&#xff1f;二、毫米波雷达是什么&#xff1f;毫米波雷达的基本原理多普勒效应 前言 现阶段自动驾驶技术中&#xff0c;主要用到的传感器有摄像头、激光雷达和毫米波雷达。 摄像头的光谱从可见光到红外光谱&#xff0c;是最接近人眼的传感…

useEffect的概念以及使用(对接口)

// useEffect的概念以及使用 import {useEffect, useState} from reactconst Url"http://geek.itheima.net/v1_0/channels"function App() {// 创建状态变量const [lustGet,setLustGet]useState([]);// 渲染完了之后执行这个useEffect(() > {// 额外的操作&#x…

Vector VH6501使用CANoe工程CANDisturbanceMain进行模拟干扰测试

系列文章目录 文章目录 系列文章目录一、文档介绍二、打开工程 CANDisturbanceMain三、模拟干扰3.1 CAN_H或CAN_L短接到地3.2 CAN_H和CAN_L短接3.3 CAN_H或CAN_L短接到电源3.4 CAN_H和CAN_L反接3.5 CAN_H和CAN_L之间的电阻/电容值调整一、文档介绍 本文档主要介绍如何使用CANo…

亚马逊测评自养号与机刷的区别

前言&#xff1a; 在亚马逊运营的领域中&#xff0c;经常有人问&#xff1a;测评自养号就是机刷吗&#xff1f;它们两者有什么区别&#xff1f;做自养号太慢、太需要时间了&#xff0c;如果用机刷的话&#xff0c;会不会简单高效一点&#xff1f; 在这篇文章中&#xff0c;我…

【字符串函数2】

5. strncpy 函数的使用和模拟实现 选择性拷贝 char * strncpy ( char * destination, const char * source, size_t num ); 1.拷贝num个字符从源字符串到目标空间。 2.如果源字符串的⻓度⼩于num&#xff0c;则拷⻉完源字符串之后&#xff0c;在⽬标的后边 追加0 &#…

STM32学习和实践笔记(35):内部温度传感器实验

1.STM32F1内部温度传感器介绍 1.1 STM32F1内部温度传感器简介 STM32F1内部含有一个温度传感器&#xff0c;可用来测量 &#xff08;STM32芯片的&#xff09;CPU 及周围的温度(TA)。&#xff08;实际并不用来测周围的温度&#xff0c;仅用来测试CPU的温度&#xff09; 此温度传…

05.VisionMaster 机器视觉 结果 格式化输出

VisionMaster 机器视觉 结果 格式化输出 格式化工具可以把数据整合并格式化成字符串输出&#xff0c;它既可以链接前面模块的结果输出&#xff0c;也可以直接在框内输入字符格&#xff0c;在进行通信输出前通常用格式化工具将数据进行整理&#xff0c; 如下图所示。 前面的文章…

网络标准架构--OSI七层、四层

OSI七层网络架构&#xff0c;以及实际使用的四层网络架构。

【C语言】13.数组指针与函数指针及其应用

一、数组指针 顾名思义&#xff0c;数组指针就是指向数组的指针。形如&#xff1a;int (*p)[10]; 注意&#xff1a;[]的优先级要高于*号的&#xff0c;所以必须加上&#xff08;&#xff09;来保证p先和*结合。 数组指针的使用 int arr[10] {0}; int (*parr)[10] &arr;…