【C语言 | 数据结构】栈

文章目录

    • 前言
    • 1、栈
      • 1.1栈的概念和定义
        • 1.1.2栈的基本概念:
      • 1.2栈的方法(接口)
      • 1.3栈的实现方法
      • 1.4栈的性质
      • 1.5栈的应用
        • 1.6栈的结构
    • 2、栈的实现
        • 2.1 顺序栈
            • 2.1.1 顺序栈的结构体
            • 2.1.2 顺序栈的初始化
            • 2.1.3 顺序栈的销毁
            • 2.1.4 顺序栈的入栈
            • 2.1.5 顺序栈的出栈
            • 2.1.5 顺序栈的判空
            • 2.1.5 顺序栈的栈顶元素
            • 2.1.5 顺序栈的有效个数
    • 2、顺序栈的完整代码实现

前言

前面讲解了数据结构中的链表、顺序表,接下来就是栈了

1、栈

1.1栈的概念和定义

是一种限定仅在表尾进行插入或删除操作的线性表。这一端被称为栈顶(top),相对地,另一端被称为栈底(bottom)。栈顶是允许操作的,而栈底是固定的。栈的插入操作通常称为进栈/压栈/入栈(PUSH),而删除操作则称为退栈/出栈(POP)。

1.1.2栈的基本概念:

栈顶(top)和栈底(bottom):

  • 栈顶:栈顶是栈中最后一个被插入或删除的元素的位置。当新的元素被添加到栈中时,它被放置在栈顶;同样,当元素从栈中被删除时,也是从栈顶开始删除的。
  • 栈底:它表示栈的起始位置或者说是最早被插入的元素所在的位置,栈底是固定的。

1.2栈的方法(接口)

  • Push(入栈/压栈):在栈顶位置压入一个新数据。
  • Pop(出栈):从栈顶位置删除一个数据。
  • Top:获取栈顶数据
  • Size:获取栈的有效数据个数
  • Empty:判断栈是否为空

1.3栈的实现方法

栈(Stack)的实现方法主要有两种:基于数组的实现和基于链表的实现。数组实现栈比较简单,需要使用realloc来扩容,使用链表来实现就不需要扩容了,可以按需申请空间,插入和删除操作的时间复杂度都为O(1)

1.4栈的性质

  1. 后进先出(LIFO):栈遵循后进先出(Last In First Out)的原则,即最后进入栈的元素将最先被移出栈。这是栈最显著的特点。
  2. 集合性:栈是由若干个元素集合而成,当没有元素的空集合称为空栈。
  3. 线性结构:栈在逻辑上呈现一种线性结构,使用数组的话在物理逻辑上是连续的,但不同于普通的线性表,栈的插入和删除操作仅在一端(栈顶)进行。
  4. 数学性质:当多个编号元素依某种顺序压入,且可任意时刻弹出时,所获得的编号元素排列的数目,恰好满足卡塔兰数列的计算,即Cn = C(2n, n) / (n+1),其中n为编号元素的个数,Cn是可能的排列数目。
  5. 栈的大小限制:栈的大小通常是有限的,当栈满时,不能再进行进栈操作,否则会引发溢出错误;当栈空时,不能再进行出栈操作,否则会引发下溢错误。

1.5栈的应用

  • 函数调用:当一个函数调用另一个函数时,操作系统会给每个线程分配一块内存空间,这块内存被组织成栈结构。每个函数调用都需要将当前状态的信息(如函数调用前的参数、局部变量和程序计数器等)保存到栈中,等到函数调用结束后再从栈中弹出这些信息,恢复调用前的状态。这个过程被称作函数的压栈和弹栈操作。
  • 表达式求值:在计算机中,对算术表达式进行求值时,通常使用栈来实现。编译器可以通过两个栈来实现,一个栈用来保存操作数,另一个栈用来保存运算符。从左到右遍历表达式,当遇到数字时,将其压入操作数栈;当遇到运算符时,与运算符栈栈顶元素进行比较,根据运算符的优先级进行相应的压栈或出栈操作,并计算表达式的值。
    系统调用:在操作系统中,内核通常会将一个系统调用的参数、返回值和程序计数器等状态保存到进程的用户栈中,在系统调用结束后再从栈中弹出这些信息,恢复调用前的状态。
    递归实现的非递归化:某些递归算法可以通过使用栈的数据结构转换为非递归形式,通过手动管理栈来模拟递归调用的过程。
1.6栈的结构

在这里插入图片描述

2、栈的实现

栈的实现可以使用数组来完成,也可以使用链表来完成,使用数组来完成相对简单,

2.1 顺序栈

顺序栈是使用顺序存储结构数组)实现的栈,即利用一段连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设一个指针(通常称为栈顶指针)指示当前栈顶元素的位置。顺序栈具有结构简单、操作方便、易于实现等优点,因此在实际应用中非常广泛。

2.1.1 顺序栈的结构体
typedef int SDataType;

typedef struct Stack
{
	SDataType* _a;
	int _top;
	int _capacity;
}Stack;

栈结构里面有三个成员,一个栈顶,一个栈的数组,一个栈的总容量

2.1.2 顺序栈的初始化
void StackInit(Stack* ps)
{
	ps->_a = NULL;

	ps->_capacity = ps->_top = 0;
}

这里有两种方法初始化,一个是top始终指向栈顶的下一个元素的索引,一个是top始终是栈顶元素的索引。

2.1.3 顺序栈的销毁
// 销毁栈
void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;

	ps->_capacity = ps->_top = 0;
}
2.1.4 顺序栈的入栈
// 入栈
void StackPush(Stack* ps, SDataType data)
{
	assert(ps);
	 
	if (ps->_top == ps->_capacity)
	{
		int _newcapacity = ps->_capacity == 0 ? 4 : ps->_capacity * 2;
		SDataType* _new_a = (SDataType*)realloc(ps, _newcapacity * sizeof(SDataType));
		if (_new_a == NULL)
		{
			perror("StackPush()::realloc()");
			exit(-1);
		}
		ps->_a = _new_a;
		ps->_capacity = _newcapacity;
	}
	ps->_a[ps->_top++] = data;
}
2.1.5 顺序栈的出栈
// 出栈
void StackPop(Stack* ps)
{
	assert(ps);
	assert(ps->_top > 0);

	ps->_top--;
}

2.1.5 顺序栈的判空
// 判空
void StackEmpty(Stack* ps)
{
	assert(ps);

	return ps->_top == 0;
}
2.1.5 顺序栈的栈顶元素
// 获取栈顶元素
void StackTop(Stack* ps)
{
	assert(ps);
	assert(ps->_top > 0);

	return ps->_a[ps->_top - 1];
}
2.1.5 顺序栈的有效个数
// 计算栈内有效个数
void StackSize(Stack* ps)
{
	assert(ps);

	return ps->_top;
}

2、顺序栈的完整代码实现

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

typedef int SDataType;

typedef struct Stack
{
	SDataType* _a;
	int _top;
	int _capacity;
}Stack;

// 初始化
void StackInit(Stack* ps)
{
	ps->_a = NULL;

	ps->_capacity = ps->_top = 0;
}

// 销毁栈
void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;

	ps->_capacity = ps->_top = 0;
}

// 入栈
void StackPush(Stack* ps, SDataType data)
{
	assert(ps);
	 
	if (ps->_top == ps->_capacity)
	{
		int _newcapacity = ps->_capacity == 0 ? 4 : ps->_capacity * 2;
		SDataType* _new_a = (SDataType*)realloc(ps, _newcapacity * sizeof(SDataType));
		if (_new_a == NULL)
		{
			perror("StackPush()::realloc()");
			exit(-1);
		}
		ps->_a = _new_a;
		ps->_capacity = _newcapacity;
	}
	ps->_a[ps->_top++] = data;
}

// 出栈
void StackPop(Stack* ps)
{
	assert(ps);
	assert(ps->_top > 0);

	ps->_top--;
}

// 计算栈内有效个数
void StackSize(Stack* ps)
{
	assert(ps);

	return ps->_top;
}

// 获取栈顶元素
void StackTop(Stack* ps)
{
	assert(ps);
	assert(ps->_top > 0);

	return ps->_a[ps->_top - 1];
}

// 判空
void StackEmpty(Stack* ps)
{
	assert(ps);

	return ps->_top == 0;
}

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

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

相关文章

聚观早报 | 比亚迪海狮07 EV上市;苹果将升级Siri

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 5月13日消息 比亚迪海狮07 EV上市 苹果将升级Siri OpenAI开发全新技术 沃尔沃EX30车型将上市 SpaceX计划新建发…

template——模板进阶(C++)

在之前的文章中&#xff0c;介绍了模板初阶&#xff1a;Cpp_桀桀桀桀桀桀的博客-CSDN博客 在本篇中将会对模板进一步的讲解。本篇中的主要内容为&#xff1a;非类型模板参数、函数模板的特化、类模板的特化&#xff08;其中包含全特化和偏特化&#xff09;&#xff0c;最后讲解…

【计算机网络篇】数据链路层(9)使用集线器的共享式以太网

文章目录 &#x1f6f8;使用同轴电缆的共享总线以太网 &#x1f386;使用集线器的共享式以太网&#x1f95a;集线器的特点 &#x1f354;10BASE-T星型以太网 &#x1f6f8;使用同轴电缆的共享总线以太网 若总线上的某个机械连接点接触不良或断开&#xff0c;则整个网络通信就不…

【前端工程化指南】Git常见操作之忽略文件

默认情况下&#xff0c;Git管理代码版本时会对所有文件进行跟踪&#xff0c;但有些时候我们并不希望项目中的一些文件上传到远程仓库或公共仓库中&#xff0c;例如密钥&#xff0c;个人隐私文件等。因此Git提供了两种忽略跟踪文件的方式.gitignore文本文件与git rm命令&#xf…

亿级流量下通用的高并发架构设计

既然是亿级用户应用&#xff0c;那么高并发必然是其架构设计的核心要素。 本文我们将介绍高并发架构设计的一些通用设计方案。 关键词&#xff1a;读/写分离、数据缓存、缓存更新、CQRS、数据分片、异步写 本文节选自电子工业出版社博文视点刚刚出版的《亿级流量系统架构设计…

Java随笔1

1.编程中组件的概念&#xff1a; 在编程中&#xff0c;组件&#xff08;Component&#xff09;通常指的是一种可重用的、模块化的代码单元&#xff0c;它封装了特定的功能或用户界面元素&#xff0c;并提供了与其他代码进行交互的接口。组件可以看作是对数据和方法的简单封装&…

ADS基础操作篇2

上篇文章《ADS基础介绍篇1》,对ADS界面,常用小工具及自带设计模板进行了介绍。ADS使用非常方便,含大量的控件和仿真模板。这篇文章我们主要讲解ADS的基础操作,包含Workspace、原理图、symbol的创建,仿真结果查看及优化。 1. 新建Workspace 添加名称及路径后,点击create…

共享充电宝语音芯片ic方案支持远程4g无线更新语音

一、简介 共享充电宝语音芯片ic方案支持远程4g无线wifi蓝牙更新语音 共享充电宝已经是遍布在大街小巷的好产品&#xff0c;解决了携带充电宝麻烦的痛点 但是很多的共享充电宝在人机交互方便&#xff0c;还做得不够好&#xff0c;比如&#xff1a;借、还设备没有语音提示&…

基于SSM的计算机课程实验管理系统的设计与实现(源码)

| 博主介绍&#xff1a;✌程序员徐师兄、8年大厂程序员经历。全网粉丝15w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f44…

AI视频教程下载:用ChatGPT制作 YouTube视频的指南

课程大纲&#xff1a; 面向 YouTuber 的 ChatGPT YouTube关键词研究 YouTube标题 YouTube缩略图 YouTube社区帖子 组织您的 YouTube 视频 本课程将通过两个不同领域的YouTube视频&#xff0c;展示如何使用Chat GPT来创建关键词、标题、缩略图、描述和社区帖子。 关键词研…

【Linux网络】Https【下】{CA认证/证书的签发与认证/安全性/总结}

文章目录 1.引入证书【为方案五铺垫】1.1再谈https1.2SSL/TLS1.3CA机构1.4理解数字签名1.4继续铺垫1.5方案五服务端申请证书回顾一二三回顾方案四方案五过程寻找方案五的漏洞客⼾端对证书进⾏认证 2.查看证书2.1查看浏览器的受信任证书发布机构2.2中间⼈有没有可能篡改该证书2.…

Postman工具介绍与安装

一、Postman介绍 Postman 乃是一款对 HTTP 协议予以支持的接口调试及测试工具&#xff0c;其突出特性在于功能强大&#xff0c;并且使用简便、易用性良好。不管是开发人员开展接口调试工作&#xff0c;还是测试人员进行接口测试任务&#xff0c;Postman 均属于首选工具之一。 接…

会声会影2024中文旗舰免费版(Corel VideoStudio)下载安装包附带会声会影软件注册机

一、软件背景及版本概述 会声会影&#xff08;Corel VideoStudio&#xff09;是由加拿大Corel公司发布的一款视频编辑软件&#xff0c;该软件以其功能丰富、操作简便而广受好评。2024年版本在继承之前版本优点的基础上&#xff0c;进行了诸多创新和改进&#xff0c;为用户提供…

2万字干货:如何从0到1搭建一套会员体系(4)

开始本节前还是一样来个灵魂发问&#xff1a;为什么产品需要用户标签&#xff0c;或者用户标签有什么意义/价值&#xff1f; 某些业务场景下使用会员等级无法满足业务需要。比如新用户激活、老用户福利以及沉默客户唤醒等等。 用户等级划分的逻辑和维度有些局限性&#xff0c;…

java项目之共享汽车管理系统(springboot+mysql+vue)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的共享汽车管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 共享汽车管理系统的主要…

什么是数据恢复软件?数据恢复软件怎么下载使用?

“我一直在寻找一款出色的 PC Android数据恢复软件&#xff0c;我可以下载。有很多&#xff0c;但大多数都需要我付钱。你能推荐一个我可以免费下载的好书吗&#xff1f; 奇客数据恢复安卓版是恢复已删除或丢失的Android数据的最安全工具。免费下载奇客数据恢复安卓版下面尝试所…

一分钟带你了解什么是等保测评

等保测评&#xff0c;即网络安全等级保护测评&#xff0c;是依据国家信息安全等级保护制度规定&#xff0c;对信息系统进行安全技术测评和安全管理测评&#xff0c;以确定系统的安全保护水平是否达到预定的安全等级要求。以下是等保测评的相关知识点总结&#xff1a; 测评概述&…

Google: 在新知识上微调大语言模型是否会鼓励产生幻觉?

摘要 当大型语言模型通过监督式微调进行对齐时,它们可能会遇到在预训练期间没有获得的新事实信息。人们经常推测,这可能会教导模型产生事实上不正确的回应的行为,因为模型被训练成生成没有基于其预先存在的知识的事实。在这项工作中,Google研究了这种暴露在新知识下对微调后模…

PCB的盘中孔

目录 一、什么时候可以在焊盘上打孔&#xff1f; 二、什么时候可以在焊盘上打孔&#xff1f; 绘制PCB时经常会遇到空间不够无法走线&#xff0c;这时我们会放置过孔使信号线穿过电路板一侧到达另一侧进行走线&#xff0c;这样既方便走线&#xff0c;也能够节省板子空间。有时…

Python悬置动刚度模拟及复数绘制

Python悬置动刚度模拟及复数绘制 1、复数绘制极坐标图2、动刚度的计算公式3、悬置动刚度的影响因素4、 AVL Excite 悬置动刚度的模拟 1、复数绘制极坐标图 # _*_ coding:UTF-8 _*_import matplotlib.pyplot as plt import numpy as np# 定义复数数组 complexNums [1.5 1.2j,…