【数据结构】手把手带你玩转线性表

前言:

哈喽大家好,我是野生的编程萌新,首先感谢大家的观看。数据结构的学习者大多有这样的想法:数据结构很重要,一定要学好,但数据结构比较抽象,有些算法理解起来很困难,学的很累。我想让大家知道的是:数据结构非常有趣,很多算法是智慧的结晶,我希望大家在学习数据结构的过程是一种愉悦的心情感受。因此我开创了《数据结构》专栏,在这里我将把数据结构内容以有趣易懂的方式展现给大家。

 1.线性表的定义

线性表,听名字我们就能感受到,是具有线一样性质的的表。举个鲜明的例子,当我们在上体育课时,一个班的人都排好队,每一排都有一个打头的,一个收尾的,每个人都知道自己前一个是谁,后面一个是谁,这样就如同一根线一样将他们串在了一起,这就可以称为线性表。线性表是数据结构中最基本的一种,它是由n(n>=0)个具有相同类型的元素组成的有限序列。具体来说,线性表由多个元素组成,每个元素都有一个唯一的前驱元素(除第一个元素外)和唯一的后继元素(除最后一个元素外)。这里我们要强调两个点:

  1. 首先它是一个序列,也就是说,元素之间是有顺序的,若存在多个元素,则第一个元素无前驱,最后一个元素无后继,其他元素都有且仅有一个前驱和后继。如果我们在站队时有同学请假,他的位置将会空出来,那就不能排成一队了(没有补位滴情况)。
  2. 线性表还强调有限,我们的班级人数都是有限的,元素个数当然也是有限的。事实上,在计算机处理的对象都是有限的,那种无限的数列,只存在于数学的概念中。

线性表逻辑结构图大致如下:

 线性表有两种存储方式,一种是顺序存储结构,即将元素依次存储在一块连续的内存中;另一种是链式存储结构,即将元素存储在不连续的内存中,通过指针将它们连接起来。我们前面学过的数组也是顺序表类型,除数组外线性表应用场景还有链表、栈、队列等。线性表是一种常见的数据结构,它具有一对一的关系、存储方式灵活、操作简单高效等特点,广泛应用于各种领域。线性表的优点是操作简单、效率高,但是它的缺点是插入和删除操作需要移动大量的元素,时间复杂度较高。在这一篇博客中我们主要介绍线性表中的顺序存储结构中的顺序表。

2.顺序存储结构——顺序表

顺序表是一种线性数据结构,它通过一组连续的存储单元来存储数据元素,元素之间的关系是一对一的关系。顺序表中的元素在内存中是按照其逻辑顺序依次存放的,可以通过元素在顺序表中的位置(下标)来访问和操作元素。听着怎么感觉顺序表这么像数组呢?顺序表的底层结构就是数组,实现了对数组的封装,实现了常用的增删查改等操作,二者主要区别如下:

  1. 结构差异:顺序表是通过一段连续的存储空间存储元素的线性表,而数组则是一种普通的数据结构,可以存储不连续的元素
  2. 动态性:顺序表的长度可以动态调整,当元素数量超过当前存储空间时,可以进行扩容;而数组的长度是固定的,需要在初始化时指定长度。

  3. 访问效率:由于顺序表的元素是连续存储的,所以在存取元素时效率较高,可以通过下标直接访问;而数组由于是按照索引存储,需要通过索引值来访问元素。

  4. 插入和删除操作效率:顺序表的插入和删除操作需要移动元素,所以效率较低;而数组的插入和删除操作由于不需要移动元素,所以效率较高。

  5. 空间占用:顺序表的存储空间由于需要动态调整,所以可能存在一定的空间浪费;而数组的存储空间是固定的,不会出现空间浪费的情况。

 顺序表有两种实现方式:静态顺序表和动态顺序表。静态顺序表是指在程序设计时,为顺序表分配了一段固定大小的存储空间,不允许进行扩容或缩容的操作。由于静态顺序表的大小是固定的,所以需要在定义时预估数据的最大规模,这可能会导致存储空间的浪费或无法满足需求的问题。下面为静态顺序表:

 动态顺序表是指在程序运行时,可以根据实际的数据规模进行动态扩容或缩容的操作。动态顺序表可以根据需要动态调整存储空间的大小,有效地利用了内存空间。但是,在扩容或缩容时需要进行数据的搬迁,会带来一定的时间开销。下面为动态顺序表:

 顺序表适用于需要频繁访问元素或根据下标查找元素的场景。在元素的插入和删除操作较少,或者已知数据规模的情况下,使用静态顺序表更为合适。在元素的插入和删除操作较多,或者数据规模不确定的情况下,使用动态顺序表更为合适。因为静态顺序表的使用确实不常见,极少情况才会使用静态顺序表,在这里我着重和大家介绍动态顺序表。

3.动态顺序表的的实现

动态顺序表的实现我们需要些一些函数来完成顺序表的初始化、销毁,插入、删除等操作,所以这里我们采用多文件的方式来实现。每一部分的函数都会详细讲解。下面为顺序表的结构代码:

typedef int SLDataType;
typedef struct SeqList
{SLDataType* a;int size;  //顺序表有效的个数int capacity;  //顺序表的空间大小
}SL;

3.1顺序表的初始化和销毁

我们在主函数通过顺序表的结构来创建一个顺序表,创建完顺序表我们要干什么呢?当然是初始化啦,我们在初始化。在这里我们将顺序表的地址传递给创建的顺序表初始化函数,用一个指针接收顺序表的地址,通过对指针的解引用我们就可以修改顺序表。在顺序表初始化的时候我们要满足:将线性表的长度和容量都设置为0,表示线性表当前为空,将分配的内存空间的起始地址也置空处理。顺序表的初始化函数代码如下:

void SLInit(SL* ps)
{ps->a = NULL;ps->size = 0;ps->capacity = 0;
}

顺序表的销毁是指将顺序表中的数据元素清空,并释放顺序表占用的存储空间,使之成为一个空表。具体步骤为下:首先,释放顺序表中存储数据元素的内存空间,然后,清空顺序表中的数据元素。注意,顺序表的销毁操作可能会导致数据丢失,所以在执行销毁操作之前,应该确保不再需要使用该顺序表中的数据。顺序表的销毁函数代码如下:

void SLDestroy(SL* ps)
{if (ps->a)free(ps->a);ps->size =0;ps->capacity = 0;
}

3.2顺序表的插入和删除

在这一小节主要和大家讲解顺序表的尾插、尾删、头插、头删、任意位置插入、任意位置删除操作。我们在顺序表的插入操作时,我们要先判断顺序表是否已满。如果顺序表已满,则需要进行扩容操作,将顺序表的容量增加一定的大小。所以在介绍顺序表的插入之前我们先写一个函数来为我们判断顺序表是否已满。我们要怎样判断顺序表是否满了呢?只需要判断顺序表中的有效元素个数和空间容量是否相等,相等就是满了呗。这个函数实现如下:

void SLCheckcapacity(SL* ps)
{if (ps->size == ps->capacity)//空间已经不足以插入数据{int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));if (tmp == NULL){perror("realloc");return 1;}ps->a = tmp;ps->capacity = newcapacity;}
}

在上面的代码中我们使用了一个三目运算符来判断顺序表的空间容量是否为0,如果为0,那么就将它的空间容量修改为4,若不是0,那么就将顺序表的空间容量进行2倍扩容(因为在C++的库中就存在顺序表扩容函数,它扩容就是扩大2倍,这里为了对标那个函数,所以就进行2倍扩容)。扩容不一定百分百成功,所以下面对扩容结果进行判断,如果扩容失败就返回realloc失败。

3.2.1顺序表的尾插和尾删

顺序表尾插操作是指将一个新元素插入到顺序表的末尾。顺序表的尾插步骤如下:

  1. 首先,判断顺序表是否已满,如果已满,则无法插入新元素,插入操作失败。
  2. 如果顺序表未满,则将待插入的新元素放入顺序表最后一个位置。
  3. 更新顺序表的长度数值,将长度加1。

 尾插操作的时间复杂度为O(1),即常数时间复杂度,因为无论顺序表的长度是多少,尾插操作都只需要进行一次操作即可完成。顺序表的尾插函数实现代码如下:

void SLpushBack(SL* ps,SLDataType x)
{assert(ps != NULL);//判断//1.空间足够用直接尾插//2.空间不够现申请空间,再进行尾插SLCheckcapacity(ps);ps->a[ps->size++] = x;//插入数据
}

顺序表的尾删操作指的是删除顺序表中的最后一个元素。顺序表的删除基本可以分为两个步骤:

  1. 找到最后一个元素的位置。顺序表的元素是按照顺序存储在内存中的,所以最后一个元素的位置就是顺序表的长度减一。
  2. 删除最后一个元素。将最后一个元素的位置上的元素删除,并将顺序表的长度减一。

为什么我会说基本可以分为两个步骤呢?当然是因为还有能偷懒的写法(●'◡'●),我们直接将顺序表的有效长度减一不直接就能实现了吗。 尾删时我们还要考虑一个因素顺序表是不是空的,所以我们写一个函数来判断一下:

bool SLisEmpty(SL* ps)
{assert(ps);return ps->size == 0;
}

首先老样子判断只想顺序表的指针是否指向空值,下面如果ps指向顺序表中的size等于0,那么返回true,否则返回false。我们来实现一下顺序表尾删函数:

void SLpopBack(SL* ps)
{assert(ps != NULL);assert(!SLisEmpty(ps));ps->size--;
}

 3.2.2顺序表的头插和头删

顺序表的头插操作即在顺序表的第一个位置插入一个元素。顺序表的头插步骤如下:

  1. 判断顺序表是否已满,如果已满则无法进行头插操作。
  2. 如果顺序表未满,则将顺序表中的所有元素向后移动一位,为要插入的元素腾出位置。从最后一个元素开始,将其移动到下一个位置,一直到第一个元素移动到第二个位置。
  3. 将要插入的元素放入顺序表的第一个位置。
  4. 更新顺序表的长度。

我们来实现一下顺序表的头插函数:

void SLpushFront(SL* ps, SLDataType x)
{assert(ps != NULL);//判断//插入情况和尾插相似SLCheckcapacity(ps);for (SLDataType i = ps->size; i > 0; i--){ps->a[i] = ps->a[i - 1];}ps->a[0] = x;ps->size++;
}

 头插操作的时间复杂度为O(n),其中n为顺序表中已有元素的个数。因为需要将已有元素后移一位,所以操作的时间复杂度与顺序表中已有元素的个数成正比。

顺序表的头删操作是指删除顺序表中第一个元素的操作。顺序表的头删的步骤如下:

  1. 判断顺序表是否为空,如果为空则无法进行头删操作。
  2. 如果顺序表不为空,则将第一个元素移除。
  3. 将后面的元素依次往前移动一位,覆盖掉被删除元素的位置。从第二个元素开始,将其移动到前一个位置,一直到最后一个元素位置。
  4. 更新顺序表的长度。

 我们来实现一下顺序表的头删函数:

void SLpopFront(SL* ps)
{assert(ps != NULL);for (SLDataType i = 0; i < ps->size - 1; i++){ps->a[i] = ps->a[i + 1];}ps->size--;
}

头删操作的时间复杂度也为O(n),因为需要将后面的元素往前移动一位,所以操作的时间复杂度与顺序表中已有元素的个数成正比。

3.2.3 顺序表的任意插入和任意删除

顺序表中的任意插入操作是指在任意位置插入一个元素。任意位置插入的具体步骤为下:

  1. 判断顺序表是否已满,如果已满则无法插入新元素,给出相应提示。
  2. 判断插入位置是否合法,即在顺序表的范围内,如果不合法则给出相应提示。
  3. 如果插入位置合法,需要将插入位置以及其后面的元素后移一个位置,为新元素腾出空间。
  4. 将要插入的元素放入插入位置。
  5. 更新顺序表的长度。

 我们来实现一下顺序表的任意插入函数:

void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);SLCheckcapacity(ps);int end = ps->size;while (end >= pos){ps->a[end] = ps->a[end-1];--end;}ps->a[pos-1] = x;ps->size++;
}

当然有的朋友喜欢任意位置之后插入,其实现代码如下:

void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);SLCheckcapacity(ps);int end = ps->size-1;while (end >= pos){ps->a[end+1] = ps->a[end];--end;}ps->a[pos] = x;ps->size++;
}

顺序表的任意位置删除操作是指在顺序表中删除指定位置的元素。任意位置删除的具体操作步骤如下:

  1. 首先判断删除位置的有效性。
  2. 将指定位置后面的所有元素向前移动一位。从删除位置开始,将删除位置后面的所有元素向前移动一位,覆盖掉删除的元素。可以使用一个循环来实现这个步骤。

  3. 将顺序表的长度减1,表示顺序表中元素的个数减少了一个。

我们来实现一下任意位置删除函数:

void SLErase(SL* ps, int pos)
{assert(ps != NULL);assert(pos >= 0 && pos < ps->size);for (SLDataType i = pos; i < ps->size - 1; i++){ps->a[i-1] = ps->a[i];}ps->size--;
}

任意位置之后删除代码实现:

void SLErase(SL* ps, int pos)
{assert(ps != NULL);assert(pos >= 0 && pos < ps->size);for (SLDataType i = pos; i < ps->size - 1; i++){ps->a[i] = ps->a[i + 1];}ps->size--;
}

4.多文件实现顺序表 

SeqList.h文件:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int SLDataType;
typedef struct SeqList
{SLDataType* a;int size;  //顺序表有效的个数int capacity;  //顺序表的空间大小
}SL;
void SLInit(SL* ps);//顺序表初始化
void SLDestroy(SL* ps);//顺序表的删除
void SLpushBack(SL* ps,SLDataType x);//尾插数据
void SLpushFront(SL* ps, SLDataType x);//头插数据
void SLpopBack(SL* ps);//尾删数据
void SLpopFront(SL* ps);//头删数据
void SLInsert(SL* ps, int pos, SLDataType x);//任意位置插入数据
void SLErase(SL* ps, int pos);//任意位置删除数据

SeqList.c文件:

#include"SeqList.h"
void SLInit(SL* ps)
{ps->a = NULL;ps->size = ps->capacity = 0;
}
void SLDestroy(SL* ps)
{if (ps->a)free(ps->a);ps->size = ps->capacity = 0;
}
void SLCheckcapacity(SL* ps)
{if (ps->size == ps->capacity)//空间已经不足以插入数据{int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));if (tmp == NULL){perror("realloc");return 1;}ps->a = tmp;ps->capacity = newcapacity;}
}
void SLpushBack(SL* ps,SLDataType x)
{assert(ps != NULL);//判断//1.空间足够用直接尾插//2.空间不够现申请空间,再进行尾插SLCheckcapacity(ps);ps->a[ps->size++] = x;//插入数据
}
void SLpushFront(SL* ps, SLDataType x)
{assert(ps != NULL);//判断//插入情况和尾插相似SLCheckcapacity(ps);for (SLDataType i = ps->size; i > 0; i--){ps->a[i] = ps->a[i - 1];}ps->a[0] = x;ps->size++;
}
bool SLisEmpty(SL* ps)
{assert(ps);return ps->size == 0;
}
void SLpopBack(SL* ps)
{assert(ps != NULL);assert(!SLisEmpty(ps));ps->size--;
}
void SLpopFront(SL* ps)
{assert(ps != NULL);for (SLDataType i = 0; i < ps->size - 1; i++){ps->a[i] = ps->a[i + 1];}ps->size--;
}
void print(SL* ps)
{for (int i = 0; i < ps->size; i++){printf("%d ", ps->a[i]);}printf("\n");
}
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);SLCheckcapacity(ps);int end = ps->size-1;while (end >= pos){ps->a[end+1] = ps->a[end];--end;}ps->a[pos] = x;ps->size++;
}
void SLErase(SL* ps, int pos)
{assert(ps != NULL);assert(pos >= 0 && pos < ps->size);for (SLDataType i = pos; i < ps->size - 1; i++){ps->a[i] = ps->a[i + 1];}ps->size--;
}

 test.c文件:

#include"SeqList.h"
void Test()
{SL sl;SLInit(&sl);SLpushBack(&sl, 1);SLpushBack(&sl, 2);SLpushBack(&sl, 3);SLpushBack(&sl, 4);SLpushBack(&sl, 5);print(&sl);SLErase(&sl, 2);print(&sl);SLInsert(&sl, 2, 6);print(&sl);
}
int main()
{Test();return 0;
}

我这里简单写一个函数来测试,测试结果为:

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

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

相关文章

弱监督语义分割-对CAM的生成过程进行改进1

一、仿射变换图像结合正则项优化CAM生成 论文&#xff1a;Self-supervised Equivariant Attention Mechanism for Weakly Supervised Semantic Segmentation &#xff08;CVPR,2020&#xff09; 1.SEAM方法 孪生网络架构&#xff08;Siamese Network Architecture&#xff09…

2024.5.10

TCP服务器端 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//设置窗口大小和窗口大小固定this->resize(727,879);this->setFixedSize(727,879);//创建…

STC8增强型单片机开发【定时器Timer⭐】

目录 一、引言 二、定时器基础知识 三、STC8定时器配置 四、代码示例 五、总结 一、引言 在单片机开发中&#xff0c;定时器&#xff08;Timer&#xff09;是一个极其重要的组件&#xff0c;它允许开发者基于时间触发各种事件或任务。STC8增强型单片机作为一款功能丰富的…

使用2G内存求20亿个数字中出现次数最多的N个

又是一个TOP -N的题目 我看了一下CSDN上大多数人的回答和GPT说的差不多&#xff0c;都是说使用哈希之类的&#xff1b; 我今天说一下我的解法&#xff0c;首先说一下不太快的基础解法 20亿数字使用uint32需要80GB&#xff0c; &#xff08;1&#xff09;分为40块读取&#…

c++opencv Project3 - License Plate Detector

俄罗斯车牌识别案例&#xff1a;实时识别车牌&#xff0c;并且读取到指定文件夹中。 惯例先展示结果图&#xff1a; 对于摄像头读取图片进行车牌匹配&#xff0c;原理和人脸识别其实是一致的。 利用训练好的模型进行匹配即可。可参考&#xff1a; 对视频实现人脸识别-CSDN博…

电能表远程抄表系统是什么?

电能表远程抄表系统是一种优秀的电力管理方法&#xff0c;它通过自动化的形式搜集、解决与分析电能表的信息&#xff0c;进而取代了传统人工抄水表方法。其主要原理是运用物联网技术、通讯技术和大数据处理技术&#xff0c;完成对电度表数据信息实时、远程控制获取和管理方法。…

探索无界知识:用 ChatGPT 的原理学习任何事物!

为避免文章重复&#xff0c;您的文本已通过更改句式、用词以及句子结构进行了修改。现在的文本应该能更好地满足去重的需求&#xff1a; 从ChatGPT原理出发&#xff0c;我们探讨GPT如何启发人类学习和构建个人知识体系。 1. 明确学习目标 机器学习必须依靠目标函数。同样&…

【Qt 开发基础体系】QMap 类和 QHash 类以及 QVector 类

文章目录 1.QMap 详解1.1 QMap 的介绍1.2 QMap 的具体用法如下1.3 QmultiMap类 2.QHash 详解3. QMap 和 QHash 的对比4. QVector 详解 1.QMap 详解 1.1 QMap 的介绍 &#x1f427;① QMap<key,T>提供一个从类型为Key的键到类型为T的值的映射。通常&#xff0c;QMap存储的…

STC8增强型单片机开发【串口调试UART⭐⭐】

目录 一、引言 二、UART基础知识 三、STC8 UART配置 四、代码示例 上列代码中所需的库函数文件&#xff1a; 引入库函数的流程&#xff1a; 五、总结 一、引言 在单片机开发中&#xff0c;串口调试&#xff08;UART&#xff09;是一种常用的通信方式&#xff0c;用于实现…

linux grep命令搜索指定路径

在Linux开发的过程中grep这个搜索命令&#xff0c;是必不可少的存在。它可以快速的搜索出来我们需要的关键字所在的位置。 有助于我们快速分析定位问题。 下面&#xff0c;分享一个简单实用的小技巧。 原始grep 最终grep grep过滤掉二进制的文件 -I选项 结论 这样子是不…

126.删除链表的倒数第N个节点(力扣)

题目描述 代码解决&#xff08;双指针&#xff09; /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, Li…

全视通助力珠海市井岸镇卫生院新院,建设智慧病房

5月6日&#xff0c;位于珠海市斗门区的井岸镇卫生院新院正式启用&#xff0c;面向市民开诊。新院各诊区就医秩序井然&#xff0c;总体情况良好。据统计&#xff0c;截至开诊当天11点30分&#xff0c;新院门诊共接诊347人次&#xff0c;预防接种81人次&#xff0c;儿童体检33人次…

网络相关笔记

IPv4地址 IPv4地址通常以“点分十进制”形式书写&#xff0c;即四个0-255之间的十进制数&#xff0c;各数之间用英文句点&#xff08;.&#xff09;分隔&#xff0c;例如&#xff1a;192.0.2.1。总共32位的地址空间可以表示大约42亿个不同的地址。 IPv4地址结构包括&#xff…

HashSet扩容机制

HashSet底层是HashMap,第一次添加的时候,table数组扩容到16,临界值是16*加载因子(默认是0.75),到达临界值进行扩容。 HashSet<Integer> hashSet = new HashSet<>();hashSet.add(5);hashSet.add(2);hashSet.add(5);hashSet.add(8);hashSet.add(1);当new一个H…

【C++STL详解(十)】--------priority_queue的模拟实现

目录 前言 一、堆的向上调整算法 二、堆的向下调整算法 三、优先队列模拟实现 Ⅰ、接口总览 Ⅱ、各个接口实现 1.构造函数 2.仿函数 3.向上调整 4.向下调整 5.其余接口 Ⅲ、完成代码 前言 上节内容我们简单的介绍了关于priority_queue的使用内容&#xff0c;我们明白…

Baidu Comate 编程插件:提升开发效率的利器

文章目录 引言简介目的 Baidu Comate插件概述定义与功能市场现状竞品分析 安装与配置VsCode 安装&#xff1a;注意事项 版本选择 核心特性详解功能介绍代码生成实时续写错误纠正 使用体验体验地址 引言 简介 基于文心大模型&#xff0c;结合百度积累多年的编程现场大数据和外…

PDF批量编辑:PDF转HTML批量操作技巧,提升文档格式转换效率

在数字化办公日益普及的今天&#xff0c;PDF&#xff08;Portable Document Format&#xff09;作为一种跨平台的文件格式&#xff0c;广泛应用于各种文档的存储和传输。然而&#xff0c;PDF文件的不可编辑性使得在某些情况下&#xff0c;我们需要将其转换为HTML格式以便更好地…

【国产SSL】哪家SSL证书可以保证数据不出境,是在国内验签

随着网络安全的重视&#xff0c;网站安装SSL证书已经是标配了。但是为什么目前常见的SSL证书都是国外的&#xff1f;数据受国外掌控&#xff0c;安全吗&#xff1f;那么哪家国产品牌是可以保证数据不出境的呢&#xff1f; 为什么目前常见的SSL证书都是国外的&#xff1f; 原因…

Java苍穹外卖05-订单状态定时处理-数据统计-导出excel

一、订单状态定时处理 1.Spring Task ①介绍 应用场景&#xff1a; ②cron表达式 https://cron.qqe2.com/ ③入门案例 2.需求分析 3.代码开发 每一分钟检查是否存在超时15分钟的订单 每天凌晨一点处理上一条处于派送中的订单 mapper&#xff1a; 二、来单提醒、客户催单 1…

手撕C语言题典——移除链表元素(单链表)

目录 前言 一.思路 1&#xff09;遍历原链表&#xff0c;找到值为 val 的节点并释放 2&#xff09;创建新链表 二.代码实现 1)大胆去try一下思路 2&#xff09;竟然报错了&#xff1f;&#xff01; 3&#xff09;完善之后的成品代码 搭配食用更佳哦~~ 数据结构之单…