【数据结构与算法】(二)线性表、顺序表、静态顺序表、动态顺序表

文章目录

  • 【数据结构与算法】(二)线性表、顺序表、静态顺序表、动态顺序表
    • 前言
    • 2.1 线性表的定义和特点
    • 2.2 线性表的类型定义
    • 2.3 线性表的顺序存储结构
      • 2.3.1 线性表的顺序存储表示(顺序表)
      • 2.3.2 静态顺序表的实现
        • 2.3.2.1 静态顺序表的头文件申明
        • 2.3.2.2 静态顺序表初始化
        • 2.3.2.3 静态顺序表销毁
        • 2.3.2.4 静态顺序表清空
        • 2.3.2.5 判断静态顺序表是否为空
        • 2.3.2.6 静态顺序表获取元素
        • 2.3.2.7 静态顺序表获取第一个匹配元素的下标
        • 2.3.2.8 静态顺序表获取一个元素的前驱元素
        • 2.3.2.9 静态顺序表获取一个元素的后继元素
        • 2.3.2.10 静态顺序表插入一个元素
        • 2.3.2.11 静态顺序表删除一个元素
        • 2.3.2.12 遍历静态顺序表并输出每一个元素
        • 2.3.2.13 测试
      • 2.3.3 动态顺序表的实现
        • 2.3.3.1 动态顺序表的头文件定义
        • 2.3.3.2 动态顺序表的初始化
        • 2.3.3.3 动态顺序表的插入操作

【数据结构与算法】(二)线性表、顺序表、静态顺序表、动态顺序表

前言

本篇文章大部分内容摘自严蔚敏、李冬梅、吴伟民编著的由人民邮电出版社出版发行的《数据结构:C语言版》。

本文中的所有代码使用C23标准的C语言实现,因此在编译时请加上-std=c2x,代码中若存在错误,欢迎大家在评论区指出。

如果觉得本篇文章对你有帮助的话,不妨点赞、收藏加关注吧!😘❤️❤️❤️

2.1 线性表的定义和特点

线性表是最基本且最常用的一种线性结构,同时也是其他数据结构的基础,尤其是单链表,是贯穿整个数据结构课程的基本技术。

在日常生活中,线性表的例子比比皆是。例如,26个英文字母(A,B,C, …, Z)、学生成绩表等。

从上面的示例中可以看出,它们的数据元素虽然不同,但同一线性表中的元素必定具有相同的特性,即属于同一数据对象,相邻数据元素之间存在着序偶关系。

诸如此类的由n(n >= 0)个数据特性相同的元素构成的有限序列称为线性表。

线性表中的元素个数n(n >= 0)定义为线性表的长度,n = 0时称为空表。

对于非空的线性表或线性结构,其特点是:

  1. 存在唯一的一个被称作“第一个”的数据元素;
  2. 存在唯一的一个被称作“最后一个”的数据元素;
  3. 除第一个之外,结构中的每个数据元素均只有一个前驱;
  4. 除最后一个之外,结构中的每个数据元素均只有一个后继。

2.2 线性表的类型定义

线性表是一个相当灵活的数据结构,其长度可以根据需要增长或缩短,即对线性表的数据元素不仅可以进行访问,而且可以进行插入和删除等操作。

下面给出线性表的抽象数据类型定义(只包含一些基本操作):

ADT List{数据对象:D = {a1, a2, ..., an},对象中每个数据元素的类型相同数据关系:R = {<a[i], a[i+1]> | 1 <= i < n, a[i], a[i+1] ∈ D}。基本操作:InitList(&L)初始条件:线性表 L 不存在。操作结果:构造一个空的线性表 L。DestoryList(&L)初始条件:线性表 L 已存在操作结果:销毁线性表 L。ClearList(&L)初始条件:线性表 L 已存在。操作结果:将线性表 L 清空。ListEmpty(L)初始条件:线性表 L 已存在。操作结果:若 L 为空表,则返回 true,否则返回 false。ListLength(L)初始条件:线性表 L 已存在。操作结果:返回线性表 L 的长度。GetElem(L, i, &e)初始条件:线性表 L 已存在,1 <= i <= ListLength(L)。操作结果:将线性表 L 中第 i 个位置的元素值返回给 e。LocateElem(L, e)初始条件:线性表 L 已存在。操作结果:在线性表 L 中查找与给定值 e 相等的元素,若找到返回其在表中的位置,否则返回 0。PriorElem(L,cur_e,&pre_e)初始条件:线性表L已存在操作结果:若cure_e是L的数据元素,且不是第一个,则用pre_e返回其前驱,否则操作失败,pre_e无定义。NextElem(L,cur_e,&next_e)初始条件:线性表L已存在。操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回其后继,否则操作失败,next_e无定义ListInsert(&L, i, e)初始条件:线性表 L 已存在,1 <= i <= ListLength(L) + 1。操作结果:在线性表 L 的第 i 个位置插入元素 e。ListDelete(&L, i, &e)初始条件:线性表 L 已存在,1 <= i <= ListLength(L)。操作结果:删除线性表 L 中第 i 个位置的元素,并用 e 返回删除的元素值。TraverseList(L)初始条件:线性表L已存在。操作结果:对线性表 L 进行遍历,在遍历过程中对 L 的每个结点访问一次。
}

2.3 线性表的顺序存储结构

2.3.1 线性表的顺序存储表示(顺序表)

线性表的顺序表示指的是用一组地址连续的存储单元一次存储线性表的数据元素,这种表示也称作线性表的顺序存储结构或顺序映像。通常,称这种存储结构的线性表为
顺序表(Sequential List),由于顺序表和程序设计语言中定义的数组类似,因此也有人将顺序表称为数组表(Array List)。

顺序表的特点有:

  1. 连续存储:逻辑上相邻的数据元素,其物理次序也是相邻的
  2. 读取速度快(随机访问):由于顺序表是连续存储的,因此,只要确定了存储顺序表的起始位置,顺序表中的任意一个数据元素都可以随机存取(因为可以通过下标直接访问任意位置的元素)。
  3. 插入和删除操作慢:由于顺序表是连续存储的,因此每次删除和插入操作时,为了保证连续存储,需要将插入位置之后的元素向前或向后移动,这就导致顺序表的插入和删除操作较慢。

根据顺序表的最大容量是否固定,我们将顺序表分为静态顺序表和动态顺序表。

其中,静态顺序表的最大容量固定,其元素个数达到最大容量时,无法再向其中插入元素。

动态顺序表在元素个数达到最大容量时,会自动扩容,一般来说都是创建一个容量比原来大的新元素域,然后将旧顺序表中的元素copy过来。

在无特殊说明的情况下,我们的顺序表指的都是静态顺序表。

2.3.2 静态顺序表的实现

2.3.2.1 静态顺序表的头文件申明

建议自己copy一下头文件,然后自己去实现一遍

在此不得不吐槽一句,虽然C23支持了bool true 和 false作为关键字,但是大多数编辑器/插件并没有完全支持,例如vscode上的c/c++插件,只能识别bool是关键字,true和false不是关键字。

#define MAX_SIZE 100typedef int ElemType;typedef struct StaticSequenceList{ElemType *elems;unsigned length;/* 使用指针封装的方法,在初始化的时候让指针指向对应函数即可 */void (*destroy)(struct StaticSequenceList *list);void (*clear)(struct StaticSequenceList *list);bool (*isEmpty)(struct StaticSequenceList list);void (*get)(struct StaticSequenceList list, unsigned i, ElemType *e);unsigned (*locate)(struct StaticSequenceList list, ElemType e);bool (*getPrior)(struct StaticSequenceList list, ElemType cur_e, ElemType *pre_e);bool (*getNext)(struct StaticSequenceList list, ElemType cur_e, ElemType *next_e);void (*insert)(struct StaticSequenceList *list, unsigned i, ElemType e);void (*delete)(struct StaticSequenceList *list, unsigned i, ElemType *e);void (*toString)(struct StaticSequenceList *list);} StaticSequenceList;void StaticSequenceList_Init(StaticSequenceList *list);void StaticSequenceList_Destroy(StaticSequenceList *list);void StaticSequenceList_Clear(StaticSequenceList *list);bool StaticSequenceList_isEmpty(StaticSequenceList list);void StaticSequenceList_Get(StaticSequenceList list, unsigned i, ElemType *e);unsigned StaticSequenceList_Locate(StaticSequenceList list, ElemType e);bool StaticSequenceList_LocatePrior(StaticSequenceList list, ElemType cur_e, ElemType *pre_e);bool StaticSequenceList_LocateNext(StaticSequenceList list, ElemType cur_e, ElemType *next_e);void StaticSequenceList_Insert(StaticSequenceList *list, unsigned i, ElemType e);void StaticSequenceList_Delete(StaticSequenceList *list, unsigned i, ElemType *e);void StaticSequenceList_toString(StaticSequenceList *list);
2.3.2.2 静态顺序表初始化
void StaticSequenceList_Init(StaticSequenceList *list)
{assert(list);list->elems = malloc(sizeof(ElemType) * MAX_SIZE);assert(list->elems);list->length = 0;list->destroy = StaticSequenceList_Destroy;list->clear = StaticSequenceList_Clear;list->isEmpty = StaticSequenceList_isEmpty;list->get = StaticSequenceList_Get;list->locate = StaticSequenceList_Locate;list->getPrior = StaticSequenceList_getPrior;list->getNext = StaticSequenceList_getNext;list->insert = StaticSequenceList_Insert;list->delete = StaticSequenceList_Delete;list->toString = StaticSequenceList_toString;
}
2.3.2.3 静态顺序表销毁
void StaticSequenceList_Destroy(StaticSequenceList *list)
{assert(list);free(list->elems);list->elems = NULL;
}
2.3.2.4 静态顺序表清空
void StaticSequenceList_Clear(StaticSequenceList *list)
{assert(list);list->length = 0;
}
2.3.2.5 判断静态顺序表是否为空
bool StaticSequenceList_isEmpty(StaticSequenceList list)
{assert(list.elems);return list.length == 0;
}
2.3.2.6 静态顺序表获取元素
void StaticSequenceList_Get(StaticSequenceList list, unsigned int i, ElemType *e)
{assert(i >= 1);assert(i <= list.length);*e = list.elems[i - 1];
}
2.3.2.7 静态顺序表获取第一个匹配元素的下标
unsigned StaticSequenceList_Locate(StaticSequenceList list, ElemType e)
{assert(list.elems);for (unsigned i = 0; i < list.length; i++){if (list.elems[i] == e)return i + 1;}return 0;
}
2.3.2.8 静态顺序表获取一个元素的前驱元素
bool StaticSequenceList_getPrior(StaticSequenceList list, ElemType cur_e, ElemType *pre_e)
{assert(list.elems);int index = -1;for (int i = 0; i < list.length; i++){if (list.elems[i] == cur_e){index = i;break;}}if (index >= 1){*pre_e = list.elems[index - 1];return 1;}elsereturn 0;
}
2.3.2.9 静态顺序表获取一个元素的后继元素
bool StaticSequenceList_getNext(StaticSequenceList list, ElemType cur_e, ElemType *next_e)
{int index = -1;for (unsigned i = 0; i < list.length; i++){if (list.elems[i] == cur_e){index = i;break;}}if (index >= 0 && index < list.length -1){*next_e = list.elems[index + 1];return 1;}else return 0;
}
2.3.2.10 静态顺序表插入一个元素
void StaticSequenceList_Insert(StaticSequenceList *list, unsigned int i, ElemType e)
{assert(list);assert(list->length < MAX_SIZE);assert(i >= 1);assert(i <= list->length + 1);for (unsigned j = list->length; j >= i; j--){list->elems[j] = list->elems[j - 1];}list->elems[i - 1] = e;list->length++;
}
2.3.2.11 静态顺序表删除一个元素
void StaticSequenceList_Delete(StaticSequenceList *list, unsigned int i, ElemType *e)
{assert(list);assert(i >= 1);assert(i <= list->length);*e = list->elems[i - 1];for (unsigned j = i; j < list->length; j++){list->elems[j - 1] = list->elems[j];}list->length--;
}
2.3.2.12 遍历静态顺序表并输出每一个元素
void StaticSequenceList_toString(StaticSequenceList *list)
{assert(list->elems != NULL);printf("list:{\n");for (unsigned i = 0; i < list->length; i++){printf("\t%d:%d\n", i + 1, list->elems[i]);}printf("}\n");
}
2.3.2.13 测试
int main()
{StaticSequenceList list;StaticSequenceList_Init(&list);bool flag = 1;int op = 0;unsigned i = 0;int e = 0;int temp_elem = 0;while (flag){list.toString(&list);puts("------------");puts("1. 插入元素");puts("2. 删除元素");puts("3. 获取元素");puts("4. 查找元素");puts("5. 查找前驱元素");puts("6. 查找后继元素");puts("7. 清空list");puts("8. 销毁list");puts("0. 退出");puts("-------------");scanf("%d", &op);switch (op){case 0:flag = 0;break;case 1:printf("请输入要插入的数据及其位置:");scanf("%d %d", &i, &e);list.insert(&list, i, e);break;case 2:printf("请输入要删除的元素位置:");scanf("%d", &i);list.delete(&list, i, &e);printf("删除的元素为:%d\n", e);break;case 3:printf("请输入要获取的元素下标:");scanf("%d", &i);list.get(list, i, &e);printf("该下标的元素为:%d\n", e);break;case 4:printf("请输入要查找的元素的值:");scanf("%d", &e);i = list.locate(list, e);if (i == 0)printf("未找到该元素\n");elseprintf("第一个找到的该元素下标为:%d\n", i);break;case 5:printf("请输入要查找其前驱的元素:");scanf("%d", &e);if (list.getPrior(list, e, &temp_elem))printf("该元素的前驱为:%d\n", temp_elem);elseprintf("未找到该元素\n");break;case 6:printf("请输入要查找其后继的元素:");scanf("%d", &e);if (list.getNext(list, e, &temp_elem))printf("该元素的后继为:%d\n", temp_elem);elseprintf("未找到该元素\n");break;case 7:list.clear(&list);break;case 8: list.destroy(&list);break;}}return 0;
}

2.3.3 动态顺序表的实现

前文提到,根据顺序表的最大容量是否固定,我们将顺序表分为静态顺序表和动态顺序表。

静态顺序表的最大容量固定,当其中的元素个数达到最大容量时,无法再向其插入元素。

动态顺序表在元素个数达到最大容量时,会自动扩容,一般来说都是创建一个容量比原来大的新元素域,然后将旧顺序表中的元素copy过来。因此,已有m个元素的动态顺序表在扩容时,需要至少m+n的存储空间,n为扩容量。

动态顺序表由于分配的空间大小可以在运行时动态决定,因此,相对于静态顺序表,动态顺序表在一定程度上可以减少部分内存开销。

2.3.3.1 动态顺序表的头文件定义

与静态顺序表相比,动态顺序表为了实现在运行时,动态分配内存空间,因此,在初始化、插入操作上有所不同,其他内容大致相同。

#ifndef STATIC_ARRAY_LIST_H
#define STATIC_ARRAY_LIST_H#define Increase_Multiple 2
#define Init_Size 10typedef int ElemType;typedef struct DynamicSequenceList{ElemType *elems;unsigned length;unsigned MAX_ZISE;  // 用来记录当前动态顺序表的最大容量,当length达到最大容量时,进行扩容。void (*destroy)(struct DynamicSequenceList *list);void (*clear)(struct DynamicSequenceList *list);bool (*isEmpty)(struct DynamicSequenceList list);void (*get)(struct DynamicSequenceList list, unsigned i, ElemType *e);unsigned (*locate)(struct DynamicSequenceList list, ElemType e);bool (*getPrior)(struct DynamicSequenceList list, ElemType cur_e, ElemType *pre_e);bool (*getNext)(struct DynamicSequenceList list, ElemType cur_e, ElemType *next_e);void (*insert)(struct DynamicSequenceList *list, unsigned i, ElemType e);void (*delete)(struct DynamicSequenceList *list, unsigned i, ElemType *e);void (*toString)(struct DynamicSequenceList *list);} DynamicSequenceList;void DynamicSequenceList_Init(DynamicSequenceList *list);void DynamicSequenceList_Destroy(DynamicSequenceList *list);void DynamicSequenceList_Clear(DynamicSequenceList *list);bool DynamicSequenceList_isEmpty(DynamicSequenceList list);void DynamicSequenceList_Get(DynamicSequenceList list, unsigned i, ElemType *e);unsigned DynamicSequenceList_Locate(DynamicSequenceList list, ElemType e);bool DynamicSequenceList_getPrior(DynamicSequenceList list, ElemType cur_e, ElemType *pre_e);bool DynamicSequenceList_getNext(DynamicSequenceList list, ElemType cur_e, ElemType *next_e);void DynamicSequenceList_Insert(DynamicSequenceList *list, unsigned i, ElemType e);void DynamicSequenceList_Delete(DynamicSequenceList *list, unsigned i, ElemType *e);void DynamicSequenceList_toString(DynamicSequenceList *list);#endif
2.3.3.2 动态顺序表的初始化
void DynamicSequenceList_Init(DynamicSequenceList *list)
{assert(list);list->elems = malloc(sizeof(ElemType) * Init_Size);assert(list->elems);list->length = 0;list->MAX_ZISE = Init_Size;list->destroy = DynamicSequenceList_Destroy;list->clear = DynamicSequenceList_Clear;list->isEmpty = DynamicSequenceList_isEmpty;list->get = DynamicSequenceList_Get;list->locate = DynamicSequenceList_Locate;list->getPrior = DynamicSequenceList_getPrior;list->getNext = DynamicSequenceList_getNext;list->insert = DynamicSequenceList_Insert;list->delete = DynamicSequenceList_Delete;list->toString = DynamicSequenceList_toString;
}
2.3.3.3 动态顺序表的插入操作
void DynamicSequenceList_Insert(DynamicSequenceList *list, unsigned int i, ElemType e)
{assert(list);assert(list->length < list->MAX_ZISE);assert(i >= 1);assert(i <= list->length + 1);for (unsigned j = list->length; j >= i; j--){list->elems[j] = list->elems[j - 1];}list->elems[i - 1] = e;list->length++;// 自增长if(list->length == list->MAX_ZISE){if(realloc(list->elems, sizeof(ElemType) * list->MAX_ZISE * Increase_Multiple)){list->MAX_ZISE *= Increase_Multiple;}}
}

🙌未完待续!😘❤️❤️❤️

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

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

相关文章

(学习日记)2024.04.07:UCOSIII第三十五节:互斥量实验

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

前端学习<三>CSS进阶——0102-CSS布局样式

前言 css 进阶的主要内容如下。 1、css 非布局样式 html 元素的分类和特性 css 选择器 css 常见属性&#xff08;非布局样式&#xff09; 2、css 布局相关 css 布局属性和组合解析 常见布局方案 三栏布局案例 3、动画和效果 属于 css 中最出彩的内容。 多背景多投影特…

如何用putty通过ssh连接ubuntu

1. 下载和安装PuTTY 访问PuTTY官网下载PuTTY的最新版本。 2. 打开PuTTY 解压下载的文件后&#xff0c;找到PuTTY文件并双击打开。 3. 配置SSH连接 在ubuntu下安装ssh服务在安装ssh时&#xff0c;我一直遇到一个问题&#xff0c;原因是我的虚拟机连不上网&#xff0c;反复实…

深入理解 SQL 中的数据集合和数据关联

引言 在数据库管理系统中&#xff0c;数据集合和数据关联是 SQL 查询中常见的概念。它们是构建复杂查询和分析数据的基石。本文将深入探讨 SQL 中的数据集合和数据关联&#xff0c;包括它们的概念、常见用途以及实际示例。 首先引入一下数学中的集合 集合的基本概念&#x…

加速度:电子元器件营销网站的功能和开发周期

据工信部预计&#xff0c;到2023年&#xff0c;我国电子元器件销售总额将达到2.1万亿元。随着资本的涌入&#xff0c;在这个万亿级赛道&#xff0c;市场竞争变得更加激烈的同时&#xff0c;行业数字化发展已是大势所趋。电子元器件B2B商城平台提升数据化驱动能力&#xff0c;扩…

Flutter Don‘t use ‘BuildContext‘s across async gaps.

Flutter提示Don‘t use ‘BuildContext‘s across async gaps.的解决办法—flutter里state的mounted属性

[蓝桥杯 2019 国 C] 数正方形

[蓝桥杯 2019 国 C] 数正方形 题目描述 在一个 N N N \times N NN 的点阵上&#xff0c;取其中 4 4 4 个点恰好组成一个正方形的 4 4 4 个顶点&#xff0c;一共有多少种不同的取法&#xff1f; 由于结果可能非常大&#xff0c;你只需要输出模 1 0 9 7 10^9 7 1097 的…

吴恩达机器学习笔记:第 6 周-11机器学习系统的设计(Machine Learning System Design)11.1-11.5

目录 第 6 周 11、 机器学习系统的设计(Machine Learning System Design)11.1 首先要做什么11.2 误差分析11.3 类偏斜的误差度量11.4 查准率和查全率之间的权衡11.5 机器学习的数据 第 6 周 11、 机器学习系统的设计(Machine Learning System Design) 11.1 首先要做什么 在接…

2024.3.19力扣每日一题——好子数组的最大分数

2024.3.19 题目来源我的题解方法一 双指针 题目来源 力扣每日一题&#xff1b;题序&#xff1a;1793 我的题解 方法一 双指针 左右指针初始指向k-1,k1&#xff0c;表示左右边界。参考官方题解 好子数组必须要包含 nums[k]&#xff0c;那么我们可以使用两个指针 left 和 righ…

leetcode.24. 两两交换链表中的节点

题目 给定一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后的链表。 你不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的进行节点交换。 思路 创建虚拟头节点&#xff0c;画图&#xff0c;确认步骤。 实现 /*** Definition for singly-li…

docker安装、调试qsign签名服务器

go-cqhttp 在 Docker 里早就部署好了&#xff0c;由于没有搭建 qsign 签名服务器&#xff0c;所以迟迟不敢上线。今天终于搞定了在 Docker 下安装 qsign 签名服务器了。这次用的docker市场里找到的镜像&#xff0c;下次找时间制作一个自己的镜像。 1 拉取和运行镜像&#xff1a…

设计模式:生活中的组合模式

想象一下&#xff0c;你正在组织一个大型的家庭聚会。在这个聚会中&#xff0c;你需要准备各种菜肴&#xff0c;每个菜肴又包含不同的食材。你的目标是能够以统一的方式处理整个聚会的准备工作&#xff0c;不论是处理单个食材还是一整道菜肴。 在这个场景中&#xff0c;我们可…

C# MES通信从入门到精通(9)——c#使用visual studio2019社区版部署webservice服务

前言 在上位机软件开发领域,我们经常使用调用webservice接口来和mes系统进行交互,我们在开发Mes程序之前也可以自己先模拟发布客户的webservice接口进行调用从而加快软件开发进度,本文就是详细介绍如何自己发布webservice接口。 1、创建 参考这篇博文:webservice服务创建…

C# lambda表达式

lambda表达式关于参数表达式或语句块一个神奇的例子与总结换句话说 lambda表达式 C# 中的 lambda 表达式是一种简洁的表示匿名函数的方法。Lambda 表达式特别用于 LINQ 查询、事件处理程序、回调函数等场景中&#xff0c;它使得代码更加简洁和易于阅读。 Lambda 表达式的基本…

图像处理与视觉感知---期末复习重点(6)

文章目录 一、图像分割二、间断检测2.1 概述2.2 点检测2.3 线检测2.4 边缘检测 三、边缘连接3.1 概述3.2 Hough变换3.3 例子3.4 Hough变换的具体步骤3.5 Hough变换的法线表示形式3.6 Hough变换的扩展 四、阈值处理4.1 概述4.2 计算基本全局阈值算法4.3 自适应阈值 五、基于区域…

SV学习笔记(四)

OCP Open Closed Principle 开闭原则 文章目录 随机约束和分布为什么需要随机&#xff1f;为什么需要约束&#xff1f;我们需要随机什么&#xff1f;声明随机变量的类什么是约束权重分布集合成员和inside条件约束双向约束 约束块控制打开或关闭约束内嵌约束 随机函数pre_random…

LeetCode-131. 分割回文串【字符串 动态规划 回溯】

LeetCode-131. 分割回文串【字符串 动态规划 回溯】 题目描述&#xff1a;解题思路一&#xff1a;回溯&#xff0c; 回溯三部曲解题思路二&#xff1a;0解题思路三&#xff1a;0 题目描述&#xff1a; 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个…

微信小程序中选中手机相册图片上传到服务器的方法

思路&#xff1a; 实现图片上传我们需要使用chooseImg和uploadFile这两个api。 1. 微信小程序中的chooseImg是一个API&#xff0c;用于在用户相册或相机中选择图片上传。它可以让用户在小程序中选择上传图片&#xff0c;以便进行下一步操作&#xff0c;例如将其发送给朋友或将其…

vue项目安装下载项目包,报错Clear up some disk space and try again

npm install 报错&#xff1a; Clear up some disk space and try again 解决办法&#xff1a; npm cache clean --force npm cache clear --force && npm install --no-shrinkwrap --update-binary

常用软件架构模式优缺点及应用场景

1、分层架构模式 最常见的架构模式就是分层架构或者称为 n 层架构。大部分软件架构师、设计师和开发者都对这个架构模式非常熟悉。尽管对于层的数量和类型没有具体限制&#xff0c;但大部分分层架构主要由四层组成&#xff1a;展现层、业务层、持久层和数据库层&#xff0c;如…