数据结构——顺序栈seq_stack

news2025/3/22 13:00:29

前言:大家好😍,本文主要介绍了数据结构——顺序栈

目录

一、概念

1.1 顺序栈的基本概念

1.2 顺序栈的存储结构

二、基本操作

2.1 结构体定义

2.2 初始化 

2.3 判空

2.4 判满

2.5 扩容

2.6 插入 入栈

2.7 删除 出栈

2.8 获取栈顶元素

2.9 获取有效值长度

2.10 清空

2.11 销毁

2.12 打印

2.13 测试


一、概念

顺序栈是栈的一种实现方式,它是基于顺序存储结构(通常是数组或动态分配的内存空间)实现的栈。栈是一种**后进先出(LIFO,Last In First Out)**的数据结构,这意味着最后放入栈中的元素会最先被取出。

1.1 顺序栈的基本概念

  1. 栈的定义

    • 栈是一种线性表,其操作主要在表的一端进行,这一端称为栈顶(Top),另一端称为栈底(Bottom)

    • 栈的操作遵循**后进先出(LIFO)**的原则,即最后放入栈中的元素最先被取出。

  2. 顺序栈的特点

    • 顺序栈使用连续的内存空间来存储栈中的元素,通常通过数组或动态分配的内存来实现。

    • 栈底的位置是固定的,通常用一个指针(如base)来标记栈底。

    • 栈顶的位置是动态变化的,用一个指针(如top)来表示栈顶的位置。

1.2 顺序栈的存储结构

顺序栈的存储结构通常包括以下部分:

ps是一个指向Seq_Stack结构体的指针,所以    ps可以指向结构体的成员

  • base:指向栈底的指针,标记栈的起始位置。

  • top:栈顶指针,表示栈顶的位置。top的值通常等于栈中元素的数量。

  • stacksize:表示栈的总容量,即栈可以存储的最大元素数量。

二、基本操作

2.1 结构体定义

typedef char ELEM_TYPE;
#define INITSIZE 10//*2

struct Seq_Stack
{
	ELEM_TYPE* base;//指针,用来接收malloc的返回值
	int top;//栈顶指针
	int stacksize;//当前总的格子数
};
typedef struct Seq_Stack Seq_Stack;
typedef struct Seq_Stack* PSeq_Stack;

base是一个指针,它的作用是标记栈的底部位置,也就是这块连续内存空间的起始地址。有了base,我们就能找到栈的“根基”,从而操作整个栈。无论栈顶指针top如何变化(入栈或出栈),base始终指向栈的底部,确保我们不会迷失方向。

2.2 初始化 

void Init_Seq_Stack(Seq_Stack* ps)
{
    assert(ps != NULL);

    ps->base = (ELEM_TYPE*)malloc(INITSIZE * sizeof(ELEM_TYPE));
    if (ps->base == NULL)//内存分配失败
    {
        exit(1);//程序调用exit终止运行
    }

    ps->top = 0;
    ps->stacksize = INITSIZE;
}
  • 参数Seq_Stack* ps 是一个指向Seq_Stack结构体的指针。这个结构体定义了栈的基本属性,比如栈底指针、栈顶指针和栈的容量等。

  • ps->base:这是栈底指针,用来存储malloc分配的内存地址分配完内存后,ps->base就指向了这块内存的起始位置,也就是栈的底部。malloc:这是一个动态内存分配函数,用来在堆上分配一块内存空间

  • ps->top = 0:栈顶指针top初始化为0。在顺序栈中,top的值通常表示栈中元素的数量。初始时栈为空,所以top为0。

  • ps->stacksize = INITSIZE:将栈的总容量stacksize设置为初始大小INITSIZE。这样我们就知道栈一开始可以存储多少个元素。

  • 通过ps,函数可以访问和修改这个栈的内部数据(如basetopstacksize)。

2.3 判空

//2.判空(判断顺序表有没有元素)
bool Is_Empty(Seq_Stack* ps)
{
    if (ps == NULL)
        exit(1);

    return ps->top ==0;
}
  • 这个指针ps就是用来告诉函数“我要检查的是哪一个栈”。

  • if (ps == NULL)来检查指针是否为空。如果是空的,说明传入的栈是无效的,程序会调用exit(1)终止运行,避免后续操作出错。

2.4 判满

bool Is_Full(Seq_Stack* ps)
{
    if (ps == NULL)
        return false;

    return ps->top == ps->stacksize;
}

2.5 扩容

//4.扩容
static void Inc(Seq_Stack*ps)
{
    assert(ps != NULL);
    if (ps == NULL)
        return;

    ELEM_TYPE* tmp = (ELEM_TYPE*)realloc(ps->base, ps->stacksize * sizeof(ELEM_TYPE) * 2);
    if (tmp != NULL)
        ps->base = tmp;

    ps->stacksize *= 2;
}

Inc函数用于将顺序栈的容量加倍。从而允许更多的元素入栈。

  • realloc:这是一个动态内存分配函数,用来重新分配一块内存空间。它接受两个参数:

    • 第一个参数是当前内存块的指针(这里是ps->base)。

    • 第二个参数是新的内存大小(这里是ps->stacksize * sizeof(ELEM_TYPE) * 2)。ps->stacksize是当前栈的容量,sizeof(ELEM_TYPE)是每个元素的大小,* 2表示将容量加倍。

    • tmp:这是一个临时指针,用来存储realloc返回的新内存地址。如果realloc成功,它会返回新的内存块的指针;如果失败,它会返回NULL

    • 如果tmp不为NULL,说明realloc成功,新的内存已经分配好了。此时,ps所指向的结构体中的base成员更新为tmp的值。,即让栈底指针指向新的内存地址。

    • 将栈的总容量stacksize加倍。

2.6 插入 入栈

//插入元素(入栈/压栈)   Push
bool Push(Seq_Stack* ps, ELEM_TYPE val)
{
    assert(ps != NULL);
    if (ps == NULL)
        return false;

    if (Is_Full(ps))
    {
        Inc(ps);
    }

    ps->base[ps->top] = val;
    ps->top++;

    return true;
}
  • ps->base[ps->top] = val;:将新元素val插入到栈顶位置。ps->top表示栈顶指针,ps->base[ps->top]表示栈顶位置的内存地址。这里将新元素val存储到栈顶位置。

  • ps->top++;:将栈顶指针ps->top加1,表示栈中元素的数量增加了一个。

2.7 删除 出栈

bool Pop(Seq_Stack* ps)
{
    assert(ps != NULL);
    if (ps == NULL)
        return false;

    if (Is_Empty(ps))
        return false;

    ps->top--;

    return true;
}

2.8 获取栈顶元素

ELEM_TYPE Top(Seq_Stack* ps)
{
    assert(ps != NULL);
    if (ps == NULL)
        exit(1);

    if (Is_Empty(ps))
        exit(1);

    return ps->base[ps->top - 1];

    return true;
}
  • ps->base[ps->top - 1]:栈顶元素的索引是ps->top - 1,因为ps->top表示栈中元素的数量,而数组索引是从0开始的。因此,ps->base[ps->top - 1]表示栈顶元素的值。

2.9 获取有效值长度

//5.获取有效值长度  Size
int Get_length(Seq_Stack* ps)
{
    assert(ps != NULL);
    if (ps == NULL)
        return -1;

    return ps->top;
}

2.10 清空

//6.清空  不需要free
void Clear(Seq_Stack* ps)
{
    assert(ps != NULL);
    if (ps == NULL)
        return;

    ps->top = 0;
}

2.11 销毁

//7.销毁 需要free
void Destroy(Seq_Stack* ps)
{
    assert(ps != NULL);
    if (ps == NULL)
        return;

    free(ps->base);
    ps->base = NULL;
    ps->top = ps->stacksize = 0;
}

Destroy函数的作用是销毁一个顺序栈,并释放它所占用的动态内存。 

  • 调用free(ps->base)会释放ps->base指向的内存空间。释放内存后,这块内存就不再属于程序了,程序不能再使用它。

2.12 打印

//8.打印
void Show(Seq_Stack* ps)
{
    //assert
    for (int i = 0; i < ps->top; i++)
    {
        printf("%c ", ps->base[i]);
    }
    printf("\n");
}
  • ps->base:这是栈底指针,指向栈的起始内存地址。

  • ps->base[i]:表示栈中第i个元素的值。数组名本质上是一个指向数组首元素的指针。eg:arr&arr[0]是等价的,都表示数组的起始地址。

2.13 测试

//顺序栈测试用例
int main()
{
    /*srand((unsigned int)time(NULL));
    int tmp = rand() % 29 + 1;
    printf("%d\n", tmp);*/

    Seq_Stack head;
    Init_Seq_Stack(&head);

    Push(&head, 'A');
    Push(&head, 'B');
    Push(&head, 'C');

    Show(&head);//A B C
    printf("%c\n", Top(&head));//C
    Pop(&head);//A B
    Show(&head);//A B 

    return 0;
}

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

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

相关文章

python3.13.2安装详细步骤(附安装包)

文章目录 前言一、python3.13.2下载二、python3.13.2安装详细步骤1.查看安装文件2.启动安装程序3.安装模式选择4.自定义安装配置5.高级选项设置6.执行安装7.开始安装8.安装完成8.打开软件9.安装验证 前言 在数字化时代&#xff0c;Python 已成为不可或缺的编程语言。无论是开发…

AI-Talk开发板之更换串口引脚

一、默认引脚 CSK6011A使用UART0作为Debug uart&#xff0c;AI-Talk开发板默认使用的GPIOA2和GPIOA3作为Debug uart的RX和TX&#xff0c;通过连接器CN6引出。 二 、更换到其它引脚 查看60xx_iomux_v1.0可以&#xff0c;UART0的tx和rx可以映射到很多管脚上。 结合AI-Talk开发板…

深度解读DeepSeek:源码解读 DeepSeek-V3

深度解读DeepSeek&#xff1a;开源周&#xff08;Open Source Week&#xff09;技术解读 深度解读DeepSeek&#xff1a;源码解读 DeepSeek-V3 深度解读DeepSeek&#xff1a;技术原理 深度解读DeepSeek&#xff1a;发展历程 文章目录 整体流程模型初始化模型前向传播MoE https:/…

JavaIO流的使用和修饰器模式(直击心灵版)

系列文章目录 JavaIO流的使用和修饰器模式 文章目录 系列文章目录前言一、字节流&#xff1a; 1.FileInputStream(读取文件)2.FileOutputStream(写入文件) 二、字符流&#xff1a; 1..基础字符流:2.处理流&#xff1a;3.对象处理流&#xff1a;4.转换流&#xff1a; 三、修饰器…

爬虫入门re+bs4

目录 前言 1. 导入必要的库 2. 定义获取网页HTML内容的函数 get_html 3. 定义获取数据的函数 get_data 4. 定义获取文章正文内容的函数 content_text 5. 定义获取单条课程数据的函数 get_one_course_data 6. 定义保存数据的函数 save_data 7. 定义文件名合法化处理函数 sanitiz…

MySQL身份验证的auth_socket插件

在Ubuntu 20.04 LTS上&#xff0c;MySQL 8.0默认使用auth_socket插件进行身份验证&#xff0c;可能存在意想不到的情况。 一、auth_socket插件 在使用sudo mysql或通过sudo切换用户后执行任何MySQL命令时&#xff0c;不需要输入密码或错误密码都可以正常登入mysql数据库&…

使用Gitee Go流水线部署个人项目到服务器指南

使用Gitee Go流水线部署个人项目到服务器指南 前言&#xff01;&#xff01;&#xff01; 本文解决的问题&#xff1a; 你有一台ECS服务器&#xff0c;你在上面部署了一个Java服务也就是一个jar&#xff0c;你觉着你每次手动本地打包&#xff0c;上传&#xff0c;在通过命令去…

BlockChain.java

BlockChain 区块链&#xff0c;举个栗子 注意啦&#xff0c;列子里面的hashcode相等&#xff0c;但是字符串是不一样的哦&#xff0c;之前有记录这个问题 String.hashCode()-CSDN博客

【技术简析】触觉智能RK3506 Linux星闪网关开发板:重新定义工业物联新标杆

在工业智能化与物联网深度融合的今天&#xff0c;深圳触觉智能推出首款搭载瑞芯微RK3506芯片的Linux星闪网关开发板&#xff0c;为大家技术解析。 RK3506-国产芯的硬核实力 作为瑞芯微2024年第四季度推出的入门级工业芯片平台&#xff0c;RK3506以三核Cortex-A7&#xff08;1.…

YOLO-UniOW: 高效通用开放世界目标检测模型【附论文与源码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

面向对象(进阶)(‘封装‘,‘多态‘,‘对象属性‘,‘类属性‘,‘类方法‘,‘对象方法‘及其应用场景)

‘封装’,多态’及其应用场景 一, 封装及其应用场景 封装的定义 属于面向对象的三大特征之一, 就是隐藏对象的属性和现实细节, 仅对外提供公共的访问方式.(我们学的 函数, 类, 都是封装的体现). 封装的格式 __属性名 __属性名()封装的好处和弊端 好处 提高代码的安全性.…

算法模型从入门到起飞系列——广度优先遍历(BFS)

文章目录 前言一、广度优先遍历&#xff08;BFS&#xff09;简介1.1 广度优先遍历&#xff08;BFS&#xff09;的特点1.2 广度优先遍历&#xff08;BFS&#xff09;的要素 二、广度优先遍历&#xff08;BFS&#xff09;& 深度优先遍历&#xff08;DFS&#xff09;2.1 广度优…

<项目> 主从Reactor模型的高并发服务器

目录 Reactor 概念 分类 单Reactor单线程 单Reactor多线程 多Reactor多线程 项目介绍 项目规划 模块关系 实现 TimerWheel -- 时间轮定时器 定时器系统调用 时间轮设计 通用类型Any Buffer Socket Channel Poller EventLoop&#xff08;核心&#xff09; eventfd 设计思路 …

注意力机制,本质上是在做什么?

本文以自注意机制为例&#xff0c;输入一个4*4的矩阵 如下&#xff1a; input_datatorch.tensor([[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16] ],dtypetorch.float) 得到Q和K的转置如下。 此时&#xff0c;计算QK^T ,得到如下结果 第一行第一个位置就是第一条样本和第…

使用Python在Word中创建、读取和删除列表 - 详解

目录 工具与设置 Python在Word中创建列表 使用默认样式创建有序&#xff08;编号&#xff09;列表 使用默认样式创建无序&#xff08;项目符号&#xff09;列表 创建多级列表 使用自定义样式创建列表 Python读取Word中的列表 Python从Word中删除列表 在Word中&#xff…

右键添加:新建HTML模板文件

使用注册表给Windows右键添加:新建HTML文档模板的功能_注册表右键新建-CSDN博客 新建文件有了&#xff0c;但是没有引用模板文件&#xff0c;是空文件。 默认改成 htmlfile 模板成功

Windows10配置OpenJDK11

下载 # 华为OpenJDK镜像源 https://mirrors.huaweicloud.com/openjdk/11.0.2/解压 # 解压后至于C:\Dev\Env\Java\jdk-11.0.2目录下 https://mirrors.huaweicloud.com/openjdk/11.0.2/openjdk-11.0.2_windows-x64_bin.zip编译安装 # 以管理员身份运行 CMD命令提示符 并进入JD…

统一开放世界与开放词汇检测:YOLO-UniOW无需增量学习的高效通用开放世界目标检测框架

目录 一、摘要 二、引言 三、相关工作 开放词汇对象检测 开放世界目标检测 参数高效学习 四、高效通用的开放世界目标检测 问题定义 高效的自适应决策学习 开放世界通配符学习 五、Coovally AI模型训练与应用平台 六、实验 数据集 评价指标 实施细节 定量结果 …

如何给商品一键换色?图生生AI,告别繁琐修图

在电商竞争日益激烈的今天&#xff0c;商品图片的视觉效果直接影响着消费者的购买决策。而商品颜色的展示&#xff0c;更是重中之重&#xff01;传统的图片换色方式&#xff0c;往往需要耗费设计师大量的时间和精力&#xff0c;从抠图到调色&#xff0c;再到细节调整&#xff0…

练习-班级活动(map存储键值对)

问题描述 小明的老师准备组织一次班级活动。班上一共有 n 名 (n 为偶数) 同学&#xff0c;老师想把所有的同学进行分组&#xff0c;每两名同学一组。为了公平&#xff0c;老师给每名同学随机分配了一个 n 以内的正整数作为 id&#xff0c;第 i 名同学的 id 为 ai​。 老师希望…