数据结构之栈的讲解(源代码+图解+习题)

news2024/9/23 9:26:23

        我们在学习过顺序表和链表之后,了解了使用数组存储数据,使用结构体来存储数据和有关的指针,这些都是底层的东西,链表是靠指针的链接,顺序表是靠数组的下标才能得以实现增删查改。众多数据结构其实底层都离不开数组,指针和结构体,今天我们要学习的栈也不例外,话不多说,直接上正菜!

1. 栈的概念:

        在这里我先给大家栈的图解,通过图来理解概念。

1.1 栈的组成

        栈:黑色边框及其内部空间为栈

        栈顶:开口的方向叫做栈顶

        栈底:闭口的方向叫做栈底

        栈内元素:蓝色长方形

1.2 栈的进出规则(先进后出)

        首先,我们往栈里存入或者删除数据的时候,只能在栈顶操作,也就是咱们俗话说的,从栈顶这一头进行增删的操作,那么我们入栈的顺序是1-2-3-4的时候,出栈的顺序就是4-3-2-1了。

        我们不可以在栈底或者中间直接拿出来数据,只能在栈顶拿,谁在栈顶先拿谁,肯定是最后入栈的数据在栈顶。

        所以栈的进出规则是 先进后出

        

2. 栈的底层架构的选择

        我们知道,栈的进出规则是先进后出,我们秉持着这一理念就可以在顺序表或者链表中进行改造增删查改的规则,使其变成栈。那我们该如何选择呢?是选择顺序表还是链表呢?

2.1 栈的架构为顺序表(文末有源码,是使用方案)

2.1.1 栈和顺序表的比对

        首先我们看一下用顺序表来构造栈是如何构造的。

        当我们的栈是顺序表构造的时候,我们会发现栈底就是顺序表的表头,栈顶是顺序表的表尾。那通过顺序表如何对栈进行插入数据和删除数据呢?

2.1.2 栈的插入图解

        我们对栈的插入,一定是在栈顶这边插入,那我们对比一下这两张图,在栈顶插入就相当于顺序表的尾插对吧!我们只需要尾插顺序表就可以完成栈的插入元素了。

2.1.3 栈的删除

        栈是只能对栈顶进行增加和删除的,所以我们只能在栈顶删除元素,那是不是就相当于顺序表的尾删。

        所以对于栈的删除,我们只需要尾删顺序表就可以了。

2.2 栈的架构为链表

        而当我们使用链表作为栈的架构,什么样的链表才可以使栈的增添和删除容易呢?让我们看图一起寻找吧!

2.2.1 单链表构造栈(舍弃方案)

        当我们使用单链表构造栈的时候,栈的插入和删除都相当于对单链表的尾部进行操作,插入还好,直接尾插就行,而删除的话,删除当前节点就找不到前一个节点了,我们还需要保存前一个节点,这样很麻烦,所以这个方案是舍弃的。

2.2.2 双向链表构造栈(舍弃方案)

        对于双向链表很明显是比单链表好用,在出栈的操作,我们应该先保存栈顶元素的下一个元素的位置,也就是我们要删除图中的3,应该先保存2的位置,如果我们不保存2的位置,直接删除3,那么就找不到2的位置了。所以保存2的位置之后,删除3,再将指向3的指针 重新指向2就可以了。这个方法很明显比单链表好用,但是都没有顺序表构造的栈更方便直接,大家可以下去尝试使用双向链表模拟实现栈。

        

        最后下面我们来用代码模拟一下栈,这里首推顺序表。

3. 栈的模拟实现(源代码)

3.1 栈的定义

typedef int STDataType; 
//用顺序表模拟栈
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

3.2 栈的初始化

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

3.3 栈的销毁

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

	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}

3.4 入栈

void STPush(ST* ps, STDataType x)
{
	assert(ps);
	// 11:40
	if (ps->top == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			exit(-1);
		}

		ps->a = tmp;
		ps->capacity = newCapacity;
	}

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

3.5 取栈顶元素

STDataType STTop(ST* ps)
{
	assert(ps);

	// 
	assert(ps->top > 0);

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

3.6 出栈

void STPop(ST* ps)
{
	assert(ps);

	// 
	assert(ps->top > 0);

	--ps->top;
}

3.7 栈的元素个数

int STSize(ST* ps)
{
	assert(ps);

	return ps->top;
}

3.8 栈是否为空

bool STEmpty(ST* ps)
{
	assert(ps);

	return ps->top == 0;
}

3.9 用到的头文件

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

        以上就是栈的模拟实现了,下面我们做几个关于栈的习题。

4. 栈的习题

4.1 下列关于栈的叙述正确的是( )

        A.栈是一种“先进先出”的数据结构

        B.栈可以使用链表或顺序表来实现

        C.栈只能在栈底插入数据

        D.栈不能删除数据

答案:B

A错误:栈是一种先进后出的数据结构,队列是先进先出的。

B正确:顺序表和链表都可以用来实现栈,不过一般都使用顺序表,因为顺序表简单。

C错误:栈只能在栈顶进行输入的插入和删除操作。

D错误:栈是有入栈和出栈的操作,出栈就是从栈中删除一个元素。

4.2 一个栈的入栈序列为ABCDE,则不可能的出栈序列为( )

        A.ABCDE

        B.EDCBA

        C.DCEBA

        D.ECDBA

答案:D 

画图解决问题

4.3. 链栈与顺序栈相比,比较明显的优点是( )

        A.插入操作更加方便

        B.删除操作更加方便

        C.入栈时不需要扩容

答案:C

A错误,如果是链栈,在入栈的时候,直接尾插就行了,跟顺序栈没有多大区别。

B错误,如果是链栈,在出栈的时候,需要继续前一个节点的位置才行,要不然无法继续出栈,               而顺序栈则可以通过下标快速找到。链表的操作比顺序表复杂,因此使用顺序结构实现栈更简单。

C正确:链式结构实现栈时,每次入栈相当于链表中头插一个节点,没有扩容一说。

以上就是本次博文的分享,谢谢大家支持!

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

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

相关文章

开发ABAP程序中的错误

select语句错误 select abc from <透明表> into table <内表> where <条件>. *字段必须要一一对应.否则会报错或者值平移 select * from <透明表> into corresponding fields of table <内表> where <条件>. *虽然可以自动匹配可以避免…

分享一下门店服务预约系统怎么做

随着科技的不断发展&#xff0c;越来越多的企业开始注重提高服务质量和效率。其中&#xff0c;门店服务预约系统成为了许多企业的选择。本文将探讨门店服务预约系统的意义、设计思路、实现方法、系统测试以及拓展案例&#xff0c;并总结门店服务预约系统设计和实现的重要性。 一…

使用pycharm远程连接到Linux服务器进行开发

预计达到的效果 本地的 PyCharm 能达到和远程服务器之间的文件同步&#xff1b;本地的 PyCharm 能够使用远程服务器的开发环境&#xff1b; 环境配置 PyCharm&#xff1a;PyCharm 2021.3 (Professional Edition)Linux服务器&#xff1a;Ubuntu20.04 步骤 1.进入配置项 配…

设计模式中的黄金原则:引领你的代码风格,提升可维护性与扩展性

中国的先贤说过: 有道无术,术可求.有术无道,止于术. 术指的是技能、技术或方法&#xff0c;而道指的是原则、道德、智慧和理念。 西方古代的哲人也说过同样的话: 智慧之路从感性开始&#xff0c;却终极于理性.为什么要说设计原则呢, 因为设计模式通常需要遵循一些设计原则&…

Docker GitLab-Runner安装

Docker GitLab-Runner安装 GitLab-Runner安装 问题合集GitLab 域名的配置修改Runner容器内注册失败&#xff0c;提示 dial tcp: lookup home.zsl0.com on 192.168.254.2:53: no such host GitLab-Runner 安装 拉去gitlab/gitlab-runner镜像 docker pull gitlab/gitlab-runne…

【STL】:vector用法详解

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关vector的基础用法&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通 数…

什么是jquery

jquery是一个javascript库&#xff1b;用来简化javascript编程&#xff1b;基本是前端必备&#xff1b; 看一下示例&#xff1b; <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <script src"https://cdn.staticfile.org/j…

智慧燃气:智慧燃气推进设备全面感知及协同运营

关键词&#xff1a;智慧燃气、燃气数字化、数字燃气、智能燃气、智慧燃气建设 智慧燃气建设应用技术迭代与试点推进方面的问题。随着大数据、人工智能、物联网等新兴前沿技术不断推进和产业化&#xff0c;以及国家工业和信息化部、住房和城乡建设部、国务院国资委等部委大力推…

WMS仓储管理系统在电商领域的应用与影响

随着电商行业的快速发展&#xff0c;消费者对购物体验的要求也越来越高。而在电商运营中&#xff0c;仓储管理系统的应用对于提升购物体验和销售业绩有着重要的作用。本文将探讨WMS仓储管理系统在电商行业的应用与影响。 WMS&#xff08;Warehouse Management System&#xff0…

实战经验分享:打造千万级直播项目,如何选择适合的长连接技术,告别CRUD开发

前言 其实不管大厂、小厂&#xff0c;做业务开发的同学都知道&#xff0c;写一个功能&#xff0c;有中台&#xff0c;有架构&#xff0c;有API&#xff0c;有SDK&#xff0c;很多可复用的代码直接调一下RPC接口或者一个注解就搞定了复杂的操作&#xff0c;所以很多螺丝钉们都没…

对python中切片详解

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 Python中什么可以切片 Python中符合序列的有序序列都支持切片(slice) 如:列表,字符,元祖 &#x1f447; &#x1f447; &#x1f447; 更多精彩机密、教程&#xff0c;尽在下方&#xff0c;赶紧点击了解吧~ python源码、视…

YOLO目标检测——人体行为数据集【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;在人流量统计、行人闯入/越界检测、人群密集/拥堵检测预警等场景中&#xff0c;对监控场景中是否存在人体进行检测&#xff0c;并精确定位、追踪。数据集说明&#xff1a;&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富&#xff0c;含…

day49--动态规划8

139.单词拆分 关于多重背包&#xff0c;你该了解这些&#xff01; 背包问题总结篇&#xff01; 第一题&#xff1a;单词拆分 给定一个非空字符串 s 和一个包含非空单词的列表 wordDict&#xff0c;判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。 说明&#xff1…

[Database] MySQL 8.x Window / Partition Function (窗口/分区函数)

&#x1f9f2;相关文章 [1] MySQL 系统表解析以及各项指标查询 [2] MySQL 5.7 JSON 字段的使用的处理 [3] MySQL经典练习50题 简介 MySQL 8.0版本开始支持窗口函数 官方文档 在之前的版本中已存在的大部分聚合函数&#xff0c;在MySQL 8 中也可以作为窗口函数来使用 方法 / …

地址空间收尾-进程控制

子进程为什么能继承父进程的环境变量呢&#xff1f;并且具有全局属性&#xff1f; 通过打印地址实验可以发现&#xff0c;进程的环境变量在栈区之上 父进程的环境变量也是由bash继承下来的&#xff0c;必定有页表帮助我们从虚拟到物理的映射&#xff0c;创建子进程的页表时也会…

PowerCLI 实现email发送消息

前提条件 开启wmi,配置网卡,参考 创建发送获取信息到邮件 最终实现获取esxi 主机版本信息, esxi 主机IP,esxi开机开启状态,虚拟机名称,虚拟机IP,虚拟机开机状态,虚拟机归属哪一个物理机,发送信息到邮箱。脚本解释以下全部注释解释,请你在#部分获取。powercli-send-e…

HTML页面获取URL传递的参数值

如&#xff1a; // 查询url上链接的参数与参数值 function getQueryString(name) {var url window.location.search; // 获取URLvar pattern new RegExp("[\?\&]" name "([^\&])", "i"); // 正则匹配URLvar matcher pattern.exec(…

村田:什么是UWB无线通信?使用UWB的定位方法有哪些应用 ​

UWB是Ultra-Wide Band的缩写&#xff0c;意思是超宽带。UWB无线通信是使用超宽带的频率带宽的无线通信&#xff0c;其主要特征是能够实现高精度定位。近年来&#xff0c;已普及至智能手机防丢失、高阶汽车智能钥匙等民用设备。预计未来将在多个领域普及。 UWB无线通信技术有哪些…

浙江环保用电计量adw300-hj治污产污生产设备监测

浙江环保用电计量表&#xff0c;浙江环保用电能表&#xff0c;浙江环保督查计量电表&#xff0c;环保设备能耗采集表 企业基本信息 企业名称&#xff1a;XXXXXXXXXXX 企业地址&#xff1a;XX省XX市 工 程 量&#xff1a;X台监测仪表 预计工期&#xff1a;X天 监测点位信息…