< 数据结构 > 栈的实现

手把手教你用ObjectCRX进行Caxa二次开发:从零开始的环境搭建教程 本文是一份面向零基础初学者的Caxa二次开发实战指南,重点讲解如何使用ObjectCRX框架从零开始搭建开发环境。内容涵盖Visual Studio 2015版本锁定、ObjectCRX向导集成、项目创建、典型错误解决,并最终实现一个可在Caxa中运行的HelloWorld程序,帮助开发者快速入门并避开常见陷阱。 阅读详情

目录

前言

       栈的概念

       栈的结构

栈的实现

       创建栈结构

       初始化栈

       销毁栈

       入栈

       出栈

       获取栈顶元素

       获取栈中有效元素个数

       检测栈是否为空

总代码

       Stack.h 文件

       Stack.c 文件

       Test.c 文件


前言

栈的概念

  • 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。有点类似于手枪弹夹,后压进去的子弹总是最先打出,除非枪坏了。
  • 压栈:栈的插入操作叫做进栈/压栈/入栈。(入数据在栈顶)
  • 出栈:栈的删除操作叫做出栈。(出数据也在栈顶)

注意:

1、函数调用也有栈,这两个栈有区别吗?

当然有区别。函数调用会调用栈帧,内存里头也有一个栈,程序运行起来时要执行函数,函数里头的局部变量、参数、返回值等等都要存在函数栈帧里头。

这两个栈没有任何关联,一个是数据结构中的栈。另一个是操作系统中内存划分的一个区域,叫做栈,用来函数调用时,建立栈帧。虽然本质上没有任何关联,但都符合后进先出的规则。

2、假设入栈顺序为:1 2 3 4,那么出栈顺序一定为:4 3 2 1 吗?

当然不是。虽说规则上明确后进先出,可这是相对而言的,如果说它每进一个再出一个,然后再继续压栈,那不同样符合后进先出的规则吗。就如同上例,你说它出栈顺序为1 2 3 4 都不足为奇,每进一个出一个再进,同样符合规则。类似的入栈两个再出再进再出也是可以的,好比如2 1 4 3。

栈的结构

栈的实现

创建栈结构

  • Stack.h 文件:
//创建栈结构
typedef int STDataType;
typedef struct Stack
{
	STDataType* a; //存储数据
	int top; //栈顶的位置
	int capacity; //容量
}ST;

初始化栈

  • 思想:

初始化还是相对比较简单的,学了之前的顺序表,初始化栈就很轻松了

  • Stack.h 文件:
//初始化栈
void StackInit(ST* ps);
  • Stack.c 文件:
//初始化栈
void StackInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}
  • 注意:

​​​这里初始化的时候将top置为0是有意图的。首先,由上文创建栈结构时已经标注了,top是用来记录栈顶的位置,既然是栈顶的位置,那当top初始化为0时,我们可以直接将数据放入栈中,随后top++,但是当top初始化为-1时,top首先要++才能放入数据,因为数据不可能在负数不属于栈的位置上放入。下图演示过程:

 本文以 top = 0 示例

销毁栈

  • 思想:

动态开辟的内存空间一定要释放,free置空即可,并把其余数据置0。

  • Stack.h 文件:
//销毁栈
void StackDestory(ST* ps);
  • Stack.c 文件:
//销毁栈
void StackDestory(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->top = 0;
}

入栈

  • 思路:

前文已经强调了top初始化为0,那么理应直接压入数据,并把top++,不过在这之前,得判断空间是否够,当top=capacity的时候,栈就满了,那么就需要realloc扩容。

  • Stack.h 文件:
//压栈
void StackPush(ST* ps, STDataType x);
  • Stack.c 文件:
//压栈
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	//如果栈满了,考虑扩容
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2; //检测容量
		ps->a = (STDataType*)realloc(ps->a, newcapacity * sizeof(STDataType));
		if (ps->a == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		ps->capacity = newcapacity; //更新容量
	}
	ps->a[ps->top] = x;//将数据压进去
	ps->top++;//栈顶上移
}

出栈

  • 思路:

在你出栈之前,要确保top不为空,而top不为空的条件就是top>0,所以还要断言top>0,随后,直接将栈顶位置下移--即可。跟顺序表的思想大同小异。

  • Stack.h 文件:
//出栈
void StackPop(ST* ps);
  • Stack.c 文件:
//出栈
void StackPop(ST* ps)
{
	assert(ps);
	assert(ps->top > 0);
	ps->top--;
}

获取栈顶元素

  • 思路:

首先要搞清楚谁才是栈顶元素,是top位置还是top-1位置?很显然是top-1的位置才是栈顶元素,因为在前文初始化的时候已经明确指出top为0,当时压栈时直接放入数据的,此时第一个数据下标为0,随后++top再压入其它数据,由此可见,栈顶元素即下标top-1的位置。

  • Stack.h 文件:
//访问栈顶数据
STDataType StackTop(ST* ps);
  • Stack.c 文件:
//访问栈顶数据
STDataType StackTop(ST* ps)
{
	assert(ps);
	assert(ps->top > 0);
	return ps->a[ps->top - 1]; //top-1的位置才为栈顶的元素
}

获取栈中有效元素个数

  • 思想:

上文讲到下标top-1才是栈顶元素,那么是不是说总共就是top-1个元素呢?当然不是,这里跟数组下标一样的思想,元素个数应该就是top个,直接返回即可。

  • Stack.h 文件:
//有效元素个数
int StackSize(ST* ps);
  • Stack.c 文件:
//有效元素个数
int StackSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

检测栈是否为空

  • 思路:

当top的值为0时即为空,return直接返回即可

  • Stack.h 文件:
//判空
bool StackEmpty(ST* ps);
  • Stack.c 文件:
//判空
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0; //如果top为0,那么就为真,即返回
}
  • Test.c 文件:
void TestStack()
{
	ST st;
	StackInit(&st);
	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);
	StackPush(&st, 4);
	while (!StackEmpty(&st))
	{
		printf("%d ", StackTop(&st));
		StackPop(&st);
	}
	printf("\n");
	StackDestory(&st);
}
  • 效果如下:

总代码

Stack.h 文件

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

//创建栈结构
typedef int STDataType;
typedef struct Stack
{
	STDataType* a; //存储数据
	int top; //栈顶的位置
	int capacity; //容量
}ST;

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

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

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

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

//判空
bool StackEmpty(ST* ps);

//访问栈顶数据
STDataType StackTop(ST* ps);

//有效元素个数
int StackSize(ST* ps);

Stack.c 文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"
//初始化栈
void StackInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

//销毁栈
void StackDestory(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->top = 0;
}

//压栈
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	//如果栈满了,考虑扩容
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2; //检测容量
		ps->a = (STDataType*)realloc(ps->a, newcapacity * sizeof(STDataType));
		if (ps->a == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		ps->capacity = newcapacity; //更新容量
	}
	ps->a[ps->top] = x;//将数据压进去
	ps->top++;//栈顶上移
}
//出栈
void StackPop(ST* ps)
{
	assert(ps);
	assert(ps->top > 0);
	ps->top--;
}

//判空
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0; //如果top为0,那么就为真,即返回
}

//访问栈顶数据
STDataType StackTop(ST* ps)
{
	assert(ps);
	return ps->a[ps->top - 1]; //top-1的位置才为栈顶的元素
}

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

Test.c 文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"
void TestStack()
{
	ST st;
	StackInit(&st);
	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);
	StackPush(&st, 4);
	while (!StackEmpty(&st))
	{
		printf("%d ", StackTop(&st));
		StackPop(&st);
	}
	printf("\n");
	StackDestory(&st);
}
int main()
{
	TestStack();
	return 0;
}
51雾化器实现 1. 雾化器简介 雾化器是将试液雾化的一种器械。雾化器是原子化系统的重要部件,其性能对测定的精密度和化学干扰等产生显著影响。因此要求雾化器喷雾稳定、雾滴细小、均匀和雾化效率高。雾化器的类型有超声雾化器,空气压缩式雾化器,网式雾化器。超声雾化器因其价格合适,适合家用,被广泛应用于加湿器,香薰机等各种小家电,也在医疗领域有很多的应用。家用雾化器的主要器件是一枚雾化片。 家用雾化器分为两种不同类别雾化片,实孔雾化片和微孔雾化片,这两种的喷雾方法和工作原理是有所不同的。不同的雾化片需要特定的频率才能工作。 实孔雾 阅读详情

相关推荐

从AP到ADSP:高通8650 AudioReach中GSL-Passthru-GPR的数据通路剖析

本文深入剖析了高通骁龙8650平台AudioReach架构中,音频数据从应用处理器(AP)到音频数字信号处理器(ADSP)的完整传输路径。重点解析了GSL(Graph Service Layer)如何封装命令,并通过Passthru驱动与GPR(Generic Packet Router)协同工作,实现跨处理器的高效、异步数据交换,揭示了现代手机复杂音频系统背后的核心通信机制。

cherry的博客 536

数据结构(共享栈的实现)

数据结构中共享栈如何实现?

DMHY123的博客 862

ctf——writeup

ctf线上赛——第三关地址:http://106.75.86.18:2222提示:ip spoofing——ip伪造首先访问目标地址,一个正常的网页,挺文艺的。上面有些提示。根据上面的提示,我们浏览网页。找了好久,终于找到你。这个跳转链接。(在这个页面下方)我们接着点击这个链接,就跳转到administrator.php这个页面了。看到这个登录页面,就要知道用户名,密码,可是没有怎么办。一开始也试

Child_by_dream的博客 1320

顺序栈—栈顶指针的两种初始化

采用顺序存储的栈称之为顺序栈,它利用一组地址连续的存储单元存放自栈底到栈顶的数据元素,同时附设一个指针指示当前栈顶元素的位置。 下面给出两种栈顶指针定义的方式,讨论两种方式中在出栈、入栈代码上的不同: 1、栈顶指针top初始化为0: 入栈: 出栈: 2、 初始化栈顶指针为-1: 入栈: 出栈: ...

weixin_48334973的博客 3195

在 Zemax 非序列模式下建立干涉仪模型

Zemax 利用其相干检测功能,将到达探测器的射线的能量相干地组合起来,同时考虑每条检测到的射线的幅度和相位。从对这些干涉条纹的定量评估来看,光学干涉仪具有广泛的应用,包括在天文学中用于测量天体的大小,在计量学中用于精确测量距离,在显微镜中用于提高分辨率,以及在物理和工程的各个领域中用于检测条件的微小变化。在光学干涉仪中,使用的是光波。非相干和相干相加的总功率是守恒的,但相干光束的峰值辐照度应该是非相干光束总和的 2 倍,这是理所当然的。请注意,条纹的缺失是显而易见的,因为不再从相干的角度观察探测器。

jkh920184196的博客 2381

EDEM在农业机械设计中的实战应用:以谷物收割机优化为例

本文以谷物收割机优化为例,详细阐述了EDEM离散元仿真软件在农业机械设计中的实战应用。通过构建精准的“数字谷物”模型与农机部件动态界面,利用GPU加速完成大规模颗粒系统仿真,有效诊断并解决了籽粒夹带损失与清选负荷不均等田间难题,实现了从仿真分析到田间验证的设计优化闭环。

weixin_29256771的博客 108

栈初始化、CRUD (超详细、完整代码)

栈是只允许在一端进行插入或者删除操作的线性表。栈是一种线性表(线性表又包括顺序表和链表),栈也包括链栈和顺序栈。//链栈的实质就是 单链表使用头插法 进入只能从头进入 出来也只能从头出来int data;}*LiStack;

m0_60284144的博客 3552

线程池详解(通俗易懂超级好)

目标 【理解】线程池基本概念 【理解】线程池工作原理 【掌握】自定义线程池 【应用】java内置线程池 【应用】使用java内置线程池完成综合案例 线程池 线程池基础 线程池使用 线程池综合案例 4.学员练习 5.线程池总结 概念介绍 1:什么是线程池 2:为什么使用线程池 3:线程池有哪些优势 什么是池 什么是线程池 线程池其实就是一种多线程处理形式,处理过程中可以将任务添加到队列中,然后在创建线程后自动启动这些任务。这里的线程就是我们前面学过的线程,这里的任务就是我们前面学过的实现了Runna.

拉格朗日的学习笔记 12万+

数据结构中栈的初始化操作,进栈,出栈,获取栈顶元素,共享栈;队列的初始化,入队,出队,循环队列以及如何判断队列已满/空

数据结构中栈的初始化操作,进栈,出栈,获取栈顶元素,共享栈;队列的初始化,入队,出队,循环队列以及如何判断队列已满/空

m0_64885430的博客 832

12、硬件工程师笔试面试——MOS管(2025版本)

在设计和测试过程中,可以参考相关的EMC测试标准和指南,如CE认证EMC电磁兼容测试介绍 和电磁兼容性(EMC)测试方法与整改指南 ,以及电磁兼容(EMC)的标准与测试内容 ,来确保MOSFET的EMC性能符合行业标准。在高频应用中,MOSFET的开关速度对电路的整体性能至关重要。是一款高电压同步N沟道MOSFET驱动器,具有自举电源电压至114V的能力,宽VCC电压范围,自适应贯通保护功能,以及高达1.4A的峰值顶端栅极上拉电流,适用于分布式电源架构、汽车电源、高密度电源模块和电信系统等应用。

XU157303764的博客 7092

制作INCA和CANape通用的A2L

CANape和INCA通用的A2L配置与修改

赞的博客 5962

数据结构:栈

作为本人新开的类型,我就思考了很久,最后决定写与数据结构有关的博客。说到数据结构,我们首先想到的就是栈。 不 怎 么 华 丽 的 分 割 线 一、简介 栈,是只能在某一端插入和删除的特殊线性表。 栈和我们平时生活中的桶类似,先堆进来的压在底下,随后一件一件地往上堆。取走时,只能从上面一件一件地取走。**(先进先出)**无论是堆还是取,都在顶部进...

djc_sherlock的博客 626

使用Navicat连接Oracle数据库及ORA-12541: TNS: 无监听程序、ORA-28547:connection to server failed、ORA-12514:TNS报错解决方案

使用Navicat连接Oracle数据库及ORA-12541: TNS: 无监听程序、ORA-28547:connection to server failed、ORA-12514:TNS报错解决方案。

蓝多多的小仓库 5219

<数据结构>链栈的C语言实现

栈的概念,想必来看这篇文章的,都应该是清楚的。栈是线性表的一个子集,限定了对于表的一些操作,仅能在表尾进行插入和删除操作。话不多说,直接给出自己写的源代码(仅供参考): PS:程序简单实现,重在理解知识点,打牢基础。 "init.h": #ifndef _INIT_H #define _INIT_H #include #include #define TRUE 1 #de

云淡风轻的Blog 1249

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

<数据结构系列2>栈的实现与应用(LeetCode<有效的的括号>)

首先想要实现栈,就得知道栈为何物,以下一段摘抄至百度百科:   栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。...

102

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

数据结构<十>: 线程结构 栈的两种实现

提供一个接口  package com.mo.stack; /** * 这是栈的接口,抽象数据类型 */ public interface Stack { /** * 入栈 */ void push(Object obj) throws Exception; /** * 出栈 */ Object pop() throws Exception; /** *

weixin_38104426的博客 263

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

算法与数据结构基础<三>----数据结构基础之栈和队列加强之用栈实现队列

在上一次https://www.cnblogs.com/webor2006/p/15134809.html针对栈和队列这俩非常基础又非常重要的数据结构进行了一个加强练习,其中用队列实现了一个栈,但是还差反转的实现,也就是用栈来实现队列,上篇中发现有个小标写错了~~ 错了就错了吧,不改了,这篇之后,就木错了~~ 目标: 对于这次所编写的程序,最终也是会copy到LeetCode的这一个题上来进...

webor2006的博客 188

<学习JavaScript数据结构与算法>读书笔记之用JS实现栈和队列

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34190136的博客 147

【数据结构】栈——超详解!!!(包含栈的实现)

栈的基本概念 定义栈为一种遵循后进先出(LIFO)原则的线性数据结构。 核心操作包括压栈(push)和弹栈(pop),支持栈顶(top)访问和判空(isEmpty)等辅助操作。 栈的实现方式 数组实现:连续内存存储,需预设容量或动态扩容。 链表实现:动态节点链接,无需固定大小,但指针开销略高。 栈的典型应用场景 函数调用栈:保存函数返回地址和局部变量。 表达式求值:处理括号匹配和中缀转后缀表达式。 回溯算法:如深度优先搜索(DFS)中的路径记录。 栈的变体与扩展 最小栈:支持O(1)时间获取当前最小值

zore__的博客 2119

【数据结构】栈实现队列 & 队列实现栈

🏷️力扣地址:🌈232. 用栈实现队列请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作 实现 类:示例1: 💫关键思路:1️⃣pop接口🌠动图解析:👇🏻2️⃣peek接口🌠动图解析:👇🏻3️⃣push接口🌠动图解析:👇🏻4️⃣empty接口💡代码实现: 🏷️力扣地址:🌈225. 用队列实现栈请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(、、 和 )。实现 类:示例1 🌍解题关键:💫关键思路:那到底是如何实......

qq_42996461的博客 1838

【数据结构】用栈实现队列

本篇总结利用栈如何实现队列的相关操作,不难观察,栈和队列是可以相互转化的,需要好好总结它们的特性,构造出一个恰当的结构来实现即可,所以本篇难点不在代码思维,而是对结构的理解。

Extreme_wei的博客 4351

<数据结构> 栈Stack

一.栈stack:先进后出 FILO 1.栈的主要功能是进行数据的存储和计算 栈是一种容器 是具有特殊限制的链表或数组 2.栈的存储方式: ①顺序存储:数组 空间固定 所以需要预先知道所需要开辟的空间有多大 数组难以进行扩容 所以导致可用空间是有限的 ②链式存储:链表 栈可以理解为链表的头插头删 这种存储方式便于查找 又快又方便 3.栈的操作端为栈顶pTop 栈是没有栈底的...

avv72052的博客 203

<数据结构> 实验三:栈和队列——栈

一..实验目的      巩固栈和队列数据结构,学会运用栈和队列。 1.回顾栈和队列的逻辑结构和受限操作特点,栈和队列的物理存储结构和常见操作。 2.学习运用栈和队列的知识来解决实际问题。 3.进一步巩固程序调试方法。 4.进一步巩固模板程序设计。

xanxushh的专栏 809

【数据结构】栈的实现

【数据结构】栈如何实现

m0_59292239的博客 1288

玩转数据结构<二>栈和队列

栈 Stack 栈也是一种线性结构 相比数组,栈对应的操作是数组的子集 只能从一端添加元素,也只能从一端取出元素 这一端称为栈顶 栈是一种后进先出的结构(Last In First Out LIFO) 栈的应用 无处不在的Undo操作(撤销) 程序调用的系统栈 栈的实现 代码实现 接口代码 public interface Stack<E...

weixin_34194551的博客 108

数据结构<面试题>

1.栈和队列的共同特点是(只允许在端点处插入和删除元素) 4.栈通常采用的两种存储结构是(线性存储结构和链表存储结构) 5.下列关于栈的叙述正确的是(D) A.栈是非线性结构B.栈是一种树状结构C.栈具有先进先出的特征D.栈有后进先出的特征 6.链表不具有的特点是(B)A.不必事先估计存储空间 B.可随机访问任一元素 C.插入删除不需要移动元素 D.所需空...

itcast123的专栏 2592
上一篇: < 数据结构 > 双向带头循环链表
下一篇: < 数据结构 > 队列的实现
三分苦
三分苦 优质创作者: C/C++技术领域 优质创作者: C/C++技术领域
博客等级 码龄5年 8401粉丝 147原创
评论 101
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三分苦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值