【数据结构】栈的实现以及数组和链表的优缺点

个人主页:一代…
个人专栏:数据结构
在这里插入图片描述

1.栈

1.1栈的概念及结构

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

在这里插入图片描述
在这里插入图片描述

栈的实现

栈的实现可以用两种线性结构来实现,一种是数组,另一种是链表。

那么用哪种来实现栈比较合适呢?
那我们就要来考虑数组和链表的各自的好处了。

**学过顺序表的小伙伴都知道顺序表的底层是用数组来实现的。那么顺序表和链表有什么区别呢?

  1. 存储空间:
    顺序表的物理和逻辑上是连续的
    链表的物理上不一定连续,但逻辑上连续
  2. 随机访问
    顺序表随机访问某一个元素时时间复杂度为O(1)
    链表访问某一个元素时时间复杂度尾O(N)
  3. 在任意位置插入和删除元素
    顺序表插入和删除元素的时间复杂度为O(N)
    链表的时间复杂度为O(N)
  4. 空间利用
    动态顺序表空间不够是需要扩容,可能造成空间浪费
    链表没容量的概念,新增一个节点就malloc一个大小为STDataType的空间
  5. 缓存利用率
    顺序表的缓存利用率高
    链表的缓存利用率低

缓存利用率
在这里插入图片描述

这里主存就相当于内存,本地磁盘就相当于硬盘,这两个的一个区别就是带点和不带电的区别,内存和硬盘在带电状态下都能正常工作,但它们的工作方式和工作内容完全不同。
内存是易失性的,即当电源关闭时,内存中的数据会丢失。而硬盘是非易失性的,即使电源关闭,数据也会保留。
在不带电状态下,硬盘可以更安全地进行物理操作,而内存则无法进行任何操作(因为内存模块本身不包含任何电源或机械部件)。

    这里我浅浅讲一下顺序表和链表缓存利用率的区别

数组(顺序表)和链表在缓存利用率上的区别主要体现在它们的物理存储结构和访问方式上。
在访问一块数据内存空间时,要先把内存加载到缓存,在对其进行访问,而其并不是没此访问一个内存就将其加载到缓存,而是访问一块内存时将其后面的连续的内存一起加载到缓存,然后在对其进行访问。
数组是一块连续的内存空间,元素紧密排列,空间效率更高。这种物理空间的连续性使得数组在访问数据时具有更高的缓存利用率。当CPU执行指令运算需要访问数据时,会先去缓存中查找这个数据。如果数据已经在缓存中(缓存命中),那么CPU就可以直接从缓存中读取数据,而不需要从主存中读取,从而提高了程序的运行效率。由于数组的物理地址是连续的,因此数组中的数据在缓存中的命中率更高,减少了从主存中读取数据的次数,从而提高了缓存利用率。
相比之下,链表是由节点组成,节点之间通过引用(指针)连接。链表在添加和删除元素时只需要改变指针的指向,以节点为单位进行动态内存分配和回收,灵活并且插入和删除效率高。但是,链表的节点在物理存储上是不连续的,因此链表中的数据在缓存中的命中率相对较低。当CPU需要访问链表中的数据时,可能需要频繁地从主存中读取数据到缓存中,降低了缓存利用率,并且会造成缓存污染。
综上所述,数组(顺序表)由于物理空间的连续性,在缓存利用率上通常优于链表。这也是为什么在需要频繁访问数据的场景下,如数组的遍历、查找等操作,使用数组通常会比链表更高效。

所以链表和数组实现栈的区别并不大,但数组比链表更优一些。
(注:链表实现栈可以用单链表,用首元结点作栈顶,也可以用双链表来实现)
下面我们就开是讲解栈的实现

栈的初始化

void StackInit(Stack* ps)
{
	assert(ps);
	ps->_capacity = 0;
	//top指向栈顶数据的下一个位置
	ps->_top = 0;
	//top指向栈顶数据
	//ps->_top = -1;
	ps->_a = NULL;
}

这里初始化top既可以为0,也可以为-1,为0为top指向栈顶数据的下一个位置,为-1时指向栈顶数据。
在这里插入图片描述

栈的销毁

void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->_top = ps->_capacity = 0;
}

入栈

void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	//扩容
	if (ps->_top == ps->_capacity)
	{
		int newcapacity = ps->_capacity == 0 ? 4 : 2 * ps->_capacity;
		STDataType* tmp = (STDataType*)realloc(ps->_a, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		ps->_a = tmp;
		ps->_capacity = newcapacity;
	}
	ps->_a[ps->_top] = data;
	ps->_top++;
}

出栈

void StackPop(Stack* ps)
{
	assert(ps);
	assert(ps->_top > 0);
	ps->_top--;
}

取出栈顶元素

STDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(ps->_top > 0);
	return ps->_a[ps->_top - 1];
}

栈的大小

int StackSize(Stack* ps)
{
	assert(ps);
	return ps->_top;
}

栈是否为空

void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->_top = ps->_capacity = 0;
}

栈的全部代码
stack.h

#define  _CRT_SECURE_NO_WARNINGS 1
// 支持动态增长的栈
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int STDataType;
typedef struct Stack
{
	STDataType* _a;
	int _top;		// 栈顶
	int _capacity;  // 容量 
}Stack;
// 初始化栈 
void StackInit(Stack* ps);
// 入栈 
void StackPush(Stack* ps, STDataType data);
// 出栈 
void StackPop(Stack* ps);
// 获取栈顶元素 
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数 
int StackSize(Stack* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps);
// 销毁栈 
void StackDestroy(Stack* ps);

stack.c

#define  _CRT_SECURE_NO_WARNINGS 1
#include"stack.h"

void StackInit(Stack* ps)
{
	assert(ps);
	ps->_capacity = 0;
	//top指向栈顶数据的下一个位置
	ps->_top = 0;
	//top指向栈顶数据
	//ps->_top = -1;
	ps->_a = NULL;
}

void StackPush(Stack* ps, STDataType data)
{
	assert(ps);
	//扩容
	if (ps->_top == ps->_capacity)
	{
		int newcapacity = ps->_capacity == 0 ? 4 : 2 * ps->_capacity;
		STDataType* tmp = (STDataType*)realloc(ps->_a, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("relloc fail");
			return;
		}
		ps->_a = tmp;
		ps->_capacity = newcapacity;
	}
	ps->_a[ps->_top] = data;
	ps->_top++;
}

void StackPop(Stack* ps)
{
	assert(ps);
	assert(ps->_top > 0);
	ps->_top--;
}

STDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(ps->_top > 0);
	return ps->_a[ps->_top - 1];
}

int StackSize(Stack* ps)
{
	assert(ps);
	return ps->_top;
}

int StackEmpty(Stack* ps)
{
	assert(ps);
	return ps->_top == 0;
}

void StackDestroy(Stack* ps)
{
	assert(ps);
	free(ps->_a);
	ps->_a = NULL;
	ps->_top = ps->_capacity = 0;
}

test.c


#include"stack.h"
int main()
{
	Stack st;
	StackInit(&st);
	StackPush(&st, 5);
	StackPush(&st, 3);
	StackPush(&st, 4);
	StackPush(&st, 6);
	StackPop(&st);
	StackPop(&st);
	StackPop(&st);
	printf("%d\n",StackSize(&st));
	if (StackEmpty(&st))
	{
		printf("栈为空\n");
	}
	else
	{
		printf("栈不为空\n");
	}
	int ret=StackTop(&st);
	printf("%d\n", ret);
	if (!StackEmpty(&st))
	{
		for (int i = 0; i < st._top; i++)
		{
			printf("%d ", st._a[i]);
		}
	}
	StackDestroy(&st);
	return 0;
}

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

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

相关文章

批量自定义重命名,一键添加顺序编号,文件夹管理更高效!

我们经常需要对文件夹进行管理和整理。然而&#xff0c;当面对大量需要改名的文件夹时&#xff0c;手动逐个修改不仅效率低下&#xff0c;还容易出错。那么&#xff0c;有没有一种方法能够批量自定义重命名文件夹&#xff0c;并在名称后自动添加顺序编号呢&#xff1f;答案是肯…

C++反汇编——多态,面试题01

文章目录 1.C的三大特性1.1封装1.2继承1.3多态1.3.1 虚函数1.3.2 多态代码反汇编分析。反汇编分析1——基类指针指向子类对象&#xff0c;构造过程。反汇编分析2——基类指针指向子类对象&#xff0c;调用虚函数getPrice()过程。反汇编分析3——基类对象&#xff0c;调用虚函数…

版本控制工具之Git的基础使用教程

Git Git是一个分布式版本控制系统&#xff0c;由Linux之父Linus Torvalds 开发。它既可以用来管理和追踪计算机文件的变化&#xff0c;也是开发者协作编写代码的工具。 本文将介绍 Git 的基础原理、用法、操作等内容。 一、基础概念 1.1 版本控制系统 版本控制系统&#x…

PSoc™62开发板之IoT应用

实验目的 使用PSoc62™开发板驱动OLED模块&#xff0c;实时监控室内的光照强度、温度信息 实验准备 PSoc62™开发板SSD1309 OLED模块DS18B20温度传感器BH1750光照传感器 模块电路 SSD1309 OLED模块的电路连接和模块配置教程请参考之前的文章&#xff0c;这里不详细展开描…

汽车EDI:IAC Elmdon EDI 对接指南

近期收到客户C公司的需求&#xff0c;需要与其合作伙伴IAC Elmdon建立EDI连接&#xff0c;本文将主要为大家介绍IAC Elmdon EDI 对接指南&#xff0c;了解EDI项目的对接流程。 项目需求 传输协议&#xff1a;OFTP2 IAC Elmdon 与其供应商之间使用的传输协议为OFTP2。OFTP2是…

云南区块链商户平台优化开发

背景 云南区块链商户平台是全省统一区块链服务平台。依托于云南省发改委、阿里云及蚂蚁区块链的国内首个省级区块链平台——云南省区块链平台同步上线&#xff0c;助力数字云南整体升级。 网页版并不适合妈妈那辈人使用&#xff0c;没有记忆功能&#xff0c;于是打算自己开发…

科技查新中医学科研项目查新点如何确立与提炼?案例讲解

一、前言 医学科技查新包括立项查新和成果查新两个部分&#xff0c;其中医学立项查新&#xff0c;它是指在医学科研项目申报开题之前&#xff0c;通过在一定范围内进行该课题的相关文献检索 ( 可以根据项目委托人的具体要求&#xff0c;进行国内检索或者进行国外检索 ) &#x…

媲美Suno、Udio!AI铁了心,要砸音乐人的饭碗

5月10日凌晨&#xff0c;著名语音生成式AI平台ElevenLabs在社交平台宣布&#xff0c;推出文本生成歌曲产品ElevenLabs Music。 从其展示的效果来看&#xff0c;音乐的节奏感、和声、乐器的搭配、情感表达、创意性、风格的多样性、高/低音&#xff0c;可媲美该领域的两款头部产…

k8s StatefulSet

Statefulset 一个 Statefulset 创建的每个pod都有一个从零开始的顺序索引&#xff0c;这个会体现在 pod 的名称和主机名上&#xff0c;同样还会体现在 pod 对应的固定存储上。这些 pod 的名称是可预知的&#xff0c;它是由 Statefulset 的名称加该实例的顺序索引值组成的。不同…

【元对象系统概述】

元对象系统概述 &#x1f31f; 元对象&#x1f31f; 元对象系统&#x1f31f; QT官方文档中给出的定义&#x1f31f;《Qt5.9 C开发指南》中给出的定义 &#x1f31f; 元对象 元对象是一个描述类的信息的数据结构&#xff0c;在qt中常常与QObject的类相关联。 可以通过QObject::…

这些企业注意!推荐使用OVSSL证书

JoySSL官网 注册码230918 SSL证书作为一种重要的安全措施&#xff0c;对于确保网站数据传输的安全性至关重要。而在众多SSL证书类型中&#xff0c;OV&#xff08;Organization Validation&#xff0c;组织验证&#xff09;SSL证书以其独特的功能和适用范围&#xff0c;成为众多…

夸克网盘免费扩容N次20T的方法

上文我们用&#xff1a;夸克网盘免费领取1TB空间的方法使自己的网盘扩容到1TB&#xff0c;但只有三个月还不够大。 所以用下面的方法那个免费的把自己的网盘扩容到20TB。 一、 登录任推邦 APP 需要借助这个平台&#xff0c;这是夸克网盘的第三方服务商&#xff0c;完善注册信…

2024年自动驾驶、车辆工程与智能交通国际会议(ICADVEIT2024)

2024年自动驾驶、车辆工程与智能交通国际会议&#xff08;ICADVEIT2024&#xff09; 会议简介 2024年自动驾驶、车辆工程和智能交通国际会议&#xff08;ICADVEIT 2024&#xff09;将在中国深圳举行。会议主要聚焦自动驾驶、车辆工程和智能交通等研究领域&#xff0c;旨在为从…

智慧便民小程序源码系统 求职招聘+房产出租+相亲交友 带完整的安装代码包以及系统搭建教程

在数字化、智能化的今天&#xff0c;我们的生活节奏越来越快&#xff0c;对于各种服务的需求也越发多元化和个性化。为了满足广大市民对于便捷、高效、全面的服务需求&#xff0c;罗峰给大家分享一款智慧便民小程序源码系统&#xff0c;集求职招聘、房产出租、相亲交友三大功能…

【全开源】Java U U跑腿同城跑腿小程序源码快递代取帮买帮送源码小程序+H 5+公众号跑腿系统

特色功能&#xff1a; 智能定位与路线规划&#xff1a;UU跑腿小程序能够利用定位技术&#xff0c;为用户提供附近的跑腿服务&#xff0c;并自动规划最佳路线&#xff0c;提高配送效率。订单管理&#xff1a;包括订单查询、订单状态更新、订单评价等功能&#xff0c;全行业覆盖…

Mac YOLO V9本地训练(命令行模式)

环境&#xff1a; Mac M1 (MacOS Sonoma 14.3.1) Python 3.11PyTorch 2.1.2 一、YOLO v9工程及模型准备 详见&#xff1a;Mac YOLO V9推理测试-CSDN博客 二、数据集准备 Roboflow Universe上有许多小规模的数据集&#xff0c;很适合用来进行目标检测。 首先安装依赖 pip …

NVIDIA 配置 Jetson 扩展针座

系列文章目录 前言 每个 Jetson 开发套件包括多个扩展接头和连接器&#xff08;统称 "接头"&#xff09;&#xff1a; 40 针扩展接头&#xff1a; 可让您将 Jetson 开发套件连接到现成的 Raspberry Pi HAT&#xff08;顶部附加硬件&#xff09;&#xff0c;如 Seee…

echarts-gl 离线3D地图

1、安装依赖 echarts-gl 与 echarts 版本关系&#xff1a; "echarts": "^5.2.0", "echarts-gl": "^2.0.8"# 执行安装 yarn add echarts-gl2、下载离线地图 免费下载实时更新的geoJson数据、行政区划边界数据、区划边界坐标集合_…

笨方法自学python(一)

我觉得python和c语言有很多相似之处&#xff0c;如果有c语言基础的话学习python也不是很难。这一系列主要是学习例题来学习python&#xff1b;我用的python版本是3.12 代码编辑器我用的是notepad&#xff0c;运行py程序用cmd 现在开始写第一个程序&#xff1a; print ("…

Photoshop中绘图及图像修饰工具的应用

Photoshop中绘图及图像修饰工具的应用 Photoshop中的颜色设置与取样前景色与背景色颜色取样 Photoshop中的颜色替换工具Photoshop中的渐变工具Photoshop中的描边命令Photoshop中的填充工具采用油漆桶进行填充采用填充命令进行填充 Photoshop中的擦除工具 Photoshop中的颜色设置…
最新文章