数据结构(精讲)----栈 stack

news2025/1/23 16:02:01

什么是栈

栈是只能在一端进行插入和删除操作的线性表(又称为堆栈),进行插入和删除操作的一端称为栈顶,另一端称为栈底。

特点:栈是先进后出FILO(First In Last Out)

(LIFO(Last In First Out))

顺序栈

特性

逻辑结构:线性结构

存储结构:顺序结构

操作:创建、入栈、出栈、判空、判满

创空

入栈:

出栈

#include <stdio.h>
#include <stdlib.h>
typedef int datatype;
typedef struct seqstack
{
    int maxlen;     //表示数组元素总个数
    datatype *data; //指向存放数据的数组的指针
    int top;        //栈顶有可以称栈针,本质还是最后一个有效元素下标等同于之前学的顺序表的last
} seqstack_t;

//创建空顺序栈, len代表创建栈时的最大长度
seqstack_t *createEmptySeqStack(int len)
{
    //1. 开辟顺序栈结构体大小空间
    seqstack_t *p = (seqstack_t *)malloc(sizeof(seqstack_t));
    if (NULL == p)
    {
        perror("p malloc err");
        return NULL;
    }
    //2. 初始化结构体空间
    p->top = -1;                                          //如同之前的last初始化为-1,因为元素个数是0,下标是0-1=-1
    p->maxlen = len;                                      //保存数组长度可以通过传参获取
    p->data = (datatype *)malloc(sizeof(datatype) * len); //开辟数组大小空间,单个元素大小乘以元素个数
    if (NULL == p->data)
    {
        perror("p->data malloc err");
        return NULL;
    }

    return p;
}

//判断是否为满,满返回1 未满返回0
int isFullSeqStack(seqstack_t *p)
{
    return p->top + 1 == p->maxlen;
}

//入栈,data代表入栈的数据
int pushStack(seqstack_t *p, int data)
{
    //  1. 判满: p->top + 1 == p->maxlen
    if (isFullSeqStack(p))
    {
        printf("pushStack err\n");
        return -1;
    }
    // 让top栈顶加一
    p->top++;
    // 将数据入栈
    p->data[p->top] = data;

    return 0;
}

//判断栈是否为空
int isEmptySeqStack(seqstack_t *p)
{
    return p->top == -1;
}

//出栈
int popSeqStack(seqstack_t *p)
{
    //1.容错判断
    if (isEmptySeqStack(p))
    {
        printf("popSeqStack\n");
        return -1;
    }
    //printf("%d\n", p->data[p->top]);  //或者加打印也可以
    //2. 将栈针top减一
    p->top--;
    //3. 返回要出栈数据
    return p->data[p->top + 1];
}

int main(int argc, char const *argv[])
{
    seqstack_t *p = createEmptySeqStack(6);
    for (int i = 0; i < 7; i++)
        pushStack(p, i); //最后报一个pushStack err,因为栈满了

    while (!isEmptySeqStack(p))
        printf("%d\n", popSeqStack(p));  //5 4 3 2 1 0 后进先出
    return 0;
}

练习:

软通动力校园招聘笔试题

1. 若进栈顺序为 1,2,3,4 一下四种情况不可能出现的出栈序列是( )

A. 1,4,3,2 //入1出1入234出4出3出2

B. 2,3,4,1 //入12 出2 入3 出3 入4出4 出1

C. 3,1,4,2

D. 3,4,2,1 //入123出3入4出4出2 出1

2. 下列叙述正确的是( )

A. 线性表是线性结构

B. 栈与队列是非线性结构

C. 线性链表是非线性结构

D. 二叉树是线性结构

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

A.在栈中只能插入数据

B.在栈中只能删除数据

C.栈是先进先出的线性表

D.栈是先进后出的线性表

4. 请问下面的程序有问题吗?如果有问题在哪儿?

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

void get_mem(int *q) //q=NULL
{
    q = (int *)malloc(sizeof(int)); //改变q不会影响到函数外的p, 开辟空间也不够
}

int main(int argc, char const *argv[])
{

    int i;
    int *p = NULL;
    get_mem(p); //函数调用完成后p还是等于NULL
    for (i = 0; i < 10; i++)
        p[i] = i;

    for (i = 0; i < 10; i++)
        printf("%d\n", p[i]);

    free(p);

    return 0;
}

错误:相当于值传递,改变函数内的q不会影响到主函数的p,函数调用后p还是等于NULL。再一个开辟空间大小不够,只开辟了4字节。

修改:可以通过传递二级指针,或者返回值

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

void get_mem(int **q) //q=&p
{
    *q = (int *)malloc(sizeof(int) * 10); //*q = *&p =p ,也就是操作*q就等同操作函数外的p
}

int main(int argc, char const *argv[])
{
    int i;
    int *p = NULL;
    get_mem(&p); //函数调用结束后p真的指向了堆区
    for (i = 0; i < 10; i++)
        p[i] = i;

    for (i = 0; i < 10; i++)
        printf("%d\n", p[i]);

    free(p);

    return 0;
}

链式栈

特性:

逻辑结构:线性结构

存储结构:链式结构

顺序栈与链式栈的区别:存储结构不同,实现的方式也不同,顺序栈是用顺序表来实现的,而链式栈是用链表来实现的

栈的操作:创建、入栈、出栈、判空

入栈

出栈

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

typedef int datatype;
typedef struct node
{
    datatype data;
    struct node *next;
} node_t, *node_p;

//创建一个空栈
void createEmptyLinkStack(node_p *p) //p=&top
{
    *p = NULL; //*p = top = NULL
}

//入栈, data是入栈的数据
int pushLinkStack(node_p *p, datatype data) //因为要用p接收函数外的&top来在函数内找到top, 所以参数需要为二级指针。
{
    // 创建新节点
    node_p pnew = (node_p)malloc(sizeof(node_t));
    if (NULL == pnew)
    {
        perror("pnew malloc err");
        return -1;
    }
    // 将要入栈数据存入新节点
    pnew->data = data;
    pnew->next = NULL;
    // 将新节点连入到链表中
    pnew->next = *p; //*p=top
    // 移动栈针到新的栈顶节点
    *p = pnew;
    return 0;
}

//判断栈是否为空
int isEmptyLinkStack(node_p p)
{
    return p == NULL;
}

//出栈
datatype popLinkStack(node_p *p) //p=&top
{
    node_p pdel = NULL;
    //1. 判空:*p == NULL;
    if (isEmptyLinkStack(*p)) //*p=top
    {
        printf("popLinkStack err\n");
        return -1;
    }
    //2. 让指针pdel指向栈顶节点
    pdel = *p;
    //3. 移动栈针到下一个节点
    *p = (*p)->next; //*p=pdel->next;
    //4. 定义临时变量保存要出栈数据: temp = pdel->data;
    datatype temp = pdel->data;
    //5. 释放要被删除节点: free(pdel);
    free(pdel);
    //6. 返回要出栈数据:return temp;
    return temp;
}

//求栈的长度
int lengthLinkStack(node_p p) //传递一级指针,因为不需要移动栈针(也就是主函数的top)。
{
    int len = 0;
    while (p != NULL)
    {
        len++;
        p = p->next;
    }
    return len;
}

int main(int argc, char const *argv[])
{
    node_p top;
    createEmptyLinkStack(&top); //top=NULL
    pushLinkStack(&top, 1);
    pushLinkStack(&top, 2);
    pushLinkStack(&top, 3);

    printf("len=%d\n", lengthLinkStack(top));

    while (!isEmptyLinkStack(top))
    {
        printf("%d\n", popLinkStack(&top)); //3 2 1
    }

    return 0;
}

总结:

顺序栈和链式栈的区别是什么?

(1) 顺序栈是顺序存储,内存连续,用顺序表实现;链表是链式存储,内存不连续,用链表实现。

(2) 顺序栈的长度固定,而链栈不会。

练习:

思考:如何用两个栈实现一个队列的功能

思路:设两个栈,一个用于in一个用于out

实现入队: 如果in栈没满直接入栈,如果满了出栈之后入out栈,这样先入栈的会在out栈的栈顶。

实现出列: 如果out栈不为空直接让数据出栈,如果为空则把in栈的数据依次出栈入out栈, 这样先入栈的数据会在out栈顶。然后再把数据出out栈,来实现出列功能。

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

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

相关文章

Hexo + NexT + Github搭建个人博客

文章目录 一、 安装二、配置相关项NexT config更新主题主题样式本地实时预览常用命令 三、主题设置1.侧边栏2.页脚3.帖子发布字数统计 4.自定义自定义页面Hexo 的默认页面自定义 404 页自定义样式 5.杂项搜索服务 四、第三方插件NexT 自带插件评论系统阅读和访问人数统计 五、部…

I2S是什么通信协议?它如何传输音频数据?它和I2C是什么关系?

首先我们先明确一点&#xff0c;I2S和I2C没有什么关系&#xff0c;如果非要扯点共同点的话那就是它们都是由飞利浦制定的。 I2C我们用的比较多&#xff0c;我们用的大多数的传感器模块用的通信协议就是I2C&#xff0c;SPI&#xff0c;UART这些。 而I2S应用领域比较单一&#…

大模型:LangChain技术讲解

一、什么是LangChain 1、介绍 LangChain是一个用于开发由大型语言模型提供支持的Python框架。它提供了一系列工具和组件&#xff0c;帮助我们将语言模型集成到自己的应用程序中。 有了它之后&#xff0c;我们可以更轻松地实现对话系统、文本生成、文本分类、问答系统等功能。…

【2024 博客之星评选】请继续保持Passion

我尝试复盘自己2024年走的路&#xff0c;希望能给诸君一些借鉴。 文章目录 回头望感想与收获成长与教训今年计划感恩一些体己话 回头望 回望我的2024年&#xff0c;年初拿高绩效&#xff0c;但感觉逐渐被公司一点点剥离出中心&#xff1b;年中一直在学习防患于未然&#xff1b…

Node.js接收文件分片数据并进行合并处理

前言&#xff1a;上一篇文章讲了如何进行文件的分片&#xff1a;Vue3使用多线程处理文件分片任务&#xff0c;那么本篇文章主要看一下后端怎么接收前端上传来的分片并进行合并处理。 目录&#xff1a; 一、文件结构二、主要依赖1. express2. multer3. fs (文件系统模块)4. pat…

【2025小年源码免费送】

&#x1f496;学习知识需费心&#xff0c; &#x1f4d5;整理归纳更费神。 &#x1f389;源码免费人人喜&#xff0c; &#x1f525;码农福利等你领&#xff01; &#x1f496;山高路远坑又深&#xff0c; &#x1f4d5;大军纵横任驰奔&#xff0c; &#x1f389;谁敢横刀立马行…

【JavaSE】(8) String 类

一、String 类常用方法 1、构造方法 常用的这4种构造方法&#xff1a;直接法&#xff0c;或者传参字符串字面量、字符数组、字节数组。 在 JDK1.8 中&#xff0c;String 类的字符串实际存储在 char 数组中&#xff1a; String 类也重写了 toString 方法&#xff0c;所以可以直…

css普通用法

Css普通用法 这是一个链接 W3C&#xff0c;用这个语法可以访问W3C,自己可以去看更加详细的内容。 基本语法 名字{ 类型&#xff1a;参数 类型&#xff1a;参数 }a{ color:blue }引入方法 直接在html之中进行带入到html代码之中&#xff0c;文件不需要重新写一个&#xff0c…

大数据Hadoop中MapReduce的介绍包括编程模型、工作原理(MapReduce、MapTask、ReduceTask、Shuffle工作原理)

MapReduce概述 MapReduce是Hadoop的核心项目之一&#xff0c;它是一个分布式计算框架&#xff0c; 可用于大数据并行处理的计算模型、框架和平台&#xff0c;主要解决海量数据的计算&#xff0c;是大数据中较为熟知的分布式计算框架。 MapReduce作为分布式计算框架&#xff0…

【学习笔记】计算机网络(一)

第1章 概述 文章目录 第1章 概述1.1 计算机网络在信息时代中的作用1.2 互联网概述1.2.1 网络的网络1.2.2互联网基础结构发展的三个阶段1.2.3 互联网的标准化工作 1.3 互联网的组成1.3.1 互联网的边缘部分1.3.2 互联网的核心部分 1.4 计算机网络在我国的发展1.5 计算机网络的类别…

[OpenGL]实现屏幕空间环境光遮蔽(Screen-Space Ambient Occlusion, SSAO)

一、简介 本文介绍了 屏幕空间环境光遮蔽(Screen-Space Ambient Occlusion, SSAO) 的基本概念&#xff0c;实现流程和简单的代码实现。实现 SSAO 时使用到了 OpenGL 中的延迟着色 &#xff08;Deferred shading&#xff09;技术。 按照本文代码实现后&#xff0c;可以实现以下…

KubeSphere 开源社区 2024 年度回顾与致谢

随着 2024 年圆满落幕&#xff0c;我们回顾 KubeSphere 社区这一年走过的每一步&#xff0c;感慨万千。2024 年&#xff0c;KubeSphere 继续领跑云原生技术的创新与发展&#xff0c;推动开源文化的传播&#xff0c;致力于为全球开发者和企业用户提供更强大的平台和解决方案。感…

ToDesk云电脑、顺网云、网易云、易腾云、极云普惠云横测对比:探寻电竞最佳拍档

一、云电脑&#xff1a;电竞新宠崛起 在电竞游戏不断发展的今天&#xff0c;硬件性能成为了决定游戏体验的关键因素。为了追求极致的游戏画面与流畅度&#xff0c;玩家们往往需要投入大量资金购置高性能电脑。然而&#xff0c;云电脑技术的出现&#xff0c;为玩家们提供了一种…

GitCode 助力 AutoTable:共创 MyBatis 生态的自动表格管理新篇章

项目仓库https://gitcode.com/dromara/auto-table 解放双手&#xff0c;专注业务&#xff1a;MyBatis 生态的“自动表格”创新 AutoTable 是一款致力于为 MyBatis 生态赋予“自动表格”功能的创新插件。其核心理念是通过 Java 实体类自动生成和维护数据库的表结构&#xff0c…

【useLayoutEffect Hook】在浏览器完成布局和绘制之前执行副作用

目录 前言语法useLayoutEffect 对比 useEffect&#xff1a;示例 前言 useLayoutEffect 是 React 中的一个 Hook&#xff0c; 类似于 useEffect&#xff0c;但有一个关键的区别&#xff1a;它会在所有的 DOM 变更之后同步调用 effect。这意味着它可以读取 DOM 布局并同步重新渲…

vue3-sfc-loader 加载远程.vue文件(sfc)案例

注意事项 style标签如果增加了lang比如&#xff1a;lang“scss”&#xff0c;需要提供scss-loader的处理器&#xff0c;这个暂时没研究&#xff0c;我的处理方式是将动态模版的css放在了全局打包暂时还没有测试&#xff0c;后面测试了会同步更新 安装vue3-sfc-loader npm inst…

AIGC的企业级解决方案架构及成本效益分析

AIGC的企业级解决方案架构及成本效益分析 一,企业级解决方案架构 AIGC(人工智能生成内容)的企业级解决方案架构是一个多层次、多维度的复杂系统,旨在帮助企业实现智能化转型和业务创新。以下是总结的企业级AIGC解决方案架构的主要组成部分: 1. 技术架构 企业级AIGC解决方…

NSIS系统制作Windows下的简易的安装程序

一. 前言 NSIS&#xff08;Nullsoft Scriptable Install System&#xff09;是一个专业的开源系统&#xff0c;用于创建 Windows 安装程序。拥有小巧而灵活的特点&#xff0c;受到很多用户的赞赏。 NSIS 基于脚本语言&#xff0c;允许您创建逻辑来处理比较复杂的安装任务。 官…

leetcode-不同路径问题

一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径&#xff1f; 看见题目…

前端开发中的模拟后端与MVVM架构实践[特殊字符][特殊字符][特殊字符]

平时&#xff0c;后端可能不能及时给接口给前端进行数据调用和读取。这时候&#xff0c;前端想到进行模拟后端接口。本文将介绍如何通过vite-plugin-mock插件模拟后端接口&#xff0c;并探讨MVVM架构在前端开发中的应用。此外&#xff0c;我们还将讨论Vue2与Vue3的区别&#xf…