📌目录

  • 🔤 一,串的定义
  • 🌰 二,案例引入
    • 场景1:文本编辑器中的查找替换
    • 场景2:用户手机号验证
  • 📚 三,串的类型定义、存储结构及其运算
    • (一)串的抽象类型定义
    • (二)串的存储结构
      • 1. 顺序存储(定长顺序串)
      • 2. 堆分配存储(动态顺序串)
      • 3. 链式存储(串的链表表示)
    • (三)串的模式匹配算法
      • 1. 朴素模式匹配算法(BF算法)
      • 2. KMP算法
  • 🔢 四,数组
    • (一)数组的类型定义
    • (二)数组的顺序存储
      • 1. 一维数组
      • 2. 二维数组
    • (三)特殊矩阵的压缩存储
      • 1. 对称矩阵
      • 2. 稀疏矩阵
  • 🌐 五,广义表
    • (一)广义表的定义
    • (二)广义表的存储结构
  • 🛠️ 案例分析与实现
    • 案例:文本查找与替换工具
      • 核心思路
      • 完整代码实现
      • 代码说明
  • 📝 章结


🔤 一,串的定义

串(String),又称字符串,是由零个或多个字符组成的有限序列。通常记为 S = "a₁a₂…aₙ"(n≥0),其中:

  • S 是串名;
  • 双引号(或单引号)是串的定界符,不属于串的内容;
  • aᵢ(1≤i≤n)是单个字符,称为串的元素;
  • n 是串的长度,当 n=0 时称为空串(记为 “”)。

串的核心特点是元素的同质性——所有元素都是字符,且元素间存在明确的顺序关系。例如,“Hello” 是长度为5的串,由字符 ‘H’、‘e’、‘l’、‘l’、‘o’ 组成。

需要注意的是:

  • 空串(“”)与空格串(" ")不同,空格串的长度为空格的个数(如 " " 长度为2);
  • 串中任意连续的字符组成的子序列称为该串的子串,包含子串的串称为主串。例如,“abc” 是 “abcdef” 的子串,起始位置为1(通常从1开始计数)。

🌰 二,案例引入

场景1:文本编辑器中的查找替换

在 Word 或记事本中,当你使用“查找替换”功能,将文档中所有“数据结构”替换为“Data Structure”时:

  • 程序需要先在主串(文档内容)中定位子串“数据结构”的所有位置(模式匹配);
  • 再将这些位置的子串替换为新内容。
    这一过程的效率直接取决于串的模式匹配算法性能。

场景2:用户手机号验证

注册账号时,系统需验证输入的手机号是否为11位数字:

  • 本质是检查串的长度是否为11,且每个字符是否属于 ‘0’~‘9’。
    这一过程依赖串的基本操作(长度判断、字符遍历)。

这些案例表明,串是处理文本数据的基础结构,其存储方式和算法设计直接影响文本处理的效率。

📚 三,串的类型定义、存储结构及其运算

(一)串的抽象类型定义

串的抽象数据类型(ADT)定义如下,包含数据集合及核心操作:

ADT String {数据:由n(n≥0)个字符组成的有限序列S = "a₁a₂…aₙ",字符具有相同类型。操作:1. StrAssign(&T, chars):将字符串常量chars赋值给T。2. StrCopy(&T, S):将串S复制到串T。3. StrEmpty(S):判断串S是否为空,空则返回TRUE,否则返回FALSE。4. StrLength(S):返回串S的长度n。5. StrCompare(S, T):比较S和T,若S>T返回正数,S=T返回0,S<T返回负数。6. StrConcat(&T, S1, S2):将S1和S2拼接为新串T(T = S1 + S2)。7. SubString(&Sub, S, pos, len):从S的第pos个字符开始,截取长度为len的子串Sub。8. StrIndex(S, T, pos):从S的第pos个字符开始,查找T首次出现的位置,未找到返回0。9. StrReplace(&S, T, V):将S中所有与T相等的非重叠子串替换为V。10. StrDestroy(&S):销毁串S,释放内存。
}

(二)串的存储结构

1. 顺序存储(定长顺序串)

用固定长度的字符数组存储串,数组下标表示字符位置,另设变量记录串的实际长度(避免依赖 ‘\0’ 等结束符)。

  • 存储表示(C语言):

    #define MAXLEN 255  // 最大长度
    typedef struct {char ch[MAXLEN + 1];  // 存储字符(+1预留结束符位置)int length;           // 实际长度
    } SString;
    
  • 优势:随机访问效率高(通过下标直接获取字符);

  • 劣势:长度固定,超过MAXLEN时会截断(如存储长文本可能溢出)。

2. 堆分配存储(动态顺序串)

用动态数组存储串,长度可根据需要动态调整(通过malloc和realloc分配内存)。

  • 存储表示(C语言):

    typedef struct {char *ch;  // 指向动态分配的字符数组int length; // 实际长度
    } HString;
    
  • 初始化示例

    void InitString(HString *S) {S->ch = NULL;S->length = 0;
    }void StrAssign(HString *T, char *chars) {if (T->ch) free(T->ch); // 释放原有空间int len = strlen(chars);if (len == 0) {T->ch = NULL;T->length = 0;} else {T->ch = (char*)malloc((len + 1) * sizeof(char));strcpy(T->ch, chars); // 复制字符T->length = len;}
    }
    
  • 优势:长度灵活,适合存储不确定长度的串;

  • 劣势:动态分配可能产生内存碎片。

3. 链式存储(串的链表表示)

用单链表存储串,每个节点存储一个或多个字符(通常存储多个以提高效率,称为“块链”)。

  • 存储表示(每个节点存4个字符,C语言):

    #define CHUNKSIZE 4  // 每个节点存储的字符数
    typedef struct Chunk {char ch[CHUNKSIZE];struct Chunk *next;
    } Chunk;typedef struct {Chunk *head, *tail;  // 头指针和尾指针int length;          // 串的总长度
    } LString;
    
  • 优势:插入删除方便,适合频繁修改的场景;

  • 劣势:存储密度低(需额外存储指针),随机访问效率差。

(三)串的模式匹配算法

模式匹配是指在主串 S 中查找子串 T(模式串)首次出现的位置,是串的核心操作。

1. 朴素模式匹配算法(BF算法)

思路:从主串 S 的第 pos 个字符开始,逐个与模式串 T 的字符比较:

  • 若匹配成功,继续比较下一个字符;
  • 若匹配失败,主串回溯到上一次开始位置的下一个字符,模式串回溯到第一个字符,重新比较。

示例:在 S=“ababcabcacbab” 中查找 T=“abcac”

  • 初始从 pos=1 开始,S[1]=‘a’ 与 T[1]=‘a’ 匹配,继续比较;
  • 直到 S[4]=‘b’ 与 T[4]=‘c’ 不匹配,主串回溯到 S[2],模式串回溯到 T[1];
  • 重复过程,最终在 S[6] 处匹配成功,返回位置6。

代码实现

int Index_BF(SString S, SString T, int pos) {int i = pos;  // 主串当前位置(从1开始)int j = 1;    // 模式串当前位置while (i <= S.length && j <= T.length) {if (S.ch[i] == T.ch[j]) {i++; j++;  // 继续匹配下一个字符} else {i = i - j + 2;  // 主串回溯j = 1;          // 模式串回溯}}if (j > T.length) return i - T.length;  // 匹配成功,返回起始位置else return 0;  // 匹配失败
}

时间复杂度:最坏情况 O(n×m)(n为主串长度,m为模式串长度),适合短模式串场景。

2. KMP算法

思路:通过预处理模式串 T,得到一个“部分匹配表”(next数组),避免主串回溯,仅移动模式串:

  • next[j] 表示 T 中前 j-1 个字符的最长相等前后缀长度;
  • 匹配失败时,模式串直接跳到 next[j] 位置,主串不回溯。

优势:时间复杂度优化为 O(n + m),适合长文本匹配(如论文查重、DNA序列比对)。

🔢 四,数组

(一)数组的类型定义

数组是由相同类型的数据元素组成的有序集合,每个元素由唯一的下标(或索引)标识。

  • 一维数组:元素按线性顺序排列(如 int a[5]);
  • 二维数组:元素按行和列排列(如 int matrix[3][4],3行4列);
  • 多维数组:更高维度的扩展(如三维数组可表示立方体)。

数组的抽象数据类型定义核心操作包括:初始化、取元素(根据下标访问)、修改元素等。

(二)数组的顺序存储

数组在内存中采用顺序存储,即元素按一定次序存放在连续的内存空间中,通过下标计算元素地址。

1. 一维数组

设数组 a[n] 的基地址为 LOC(a[0]),每个元素占用 size 字节,则 a[i] 的地址为:
LOC(a[i]) = LOC(a[0]) + i × size

2. 二维数组

有两种存储方式:

  • 行优先顺序(C语言采用):先存第0行,再存第1行……第i行第j列元素 a[i][j] 的地址为:
    LOC(a[i][j]) = LOC(a[0][0]) + (i × n + j) × size(n为列数)。
  • 列优先顺序(Fortran语言采用):先存第0列,再存第1列……地址公式为:
    LOC(a[i][j]) = LOC(a[0][0]) + (j × m + i) × size(m为行数)。

(三)特殊矩阵的压缩存储

特殊矩阵(如对称矩阵、三角矩阵、对角矩阵)中存在大量重复元素或零元素,可通过压缩存储减少空间浪费。

1. 对称矩阵

若 n 阶矩阵 A 满足 A[i][j] = A[j][i](i,j=0,1,…,n-1),则只需存储下三角(含对角线)元素。

  • 元素总数为 n(n+1)/2,按行优先顺序存入一维数组 sa 中,A[i][j](i≥j)在 sa 中的下标为:
    k = i(i+1)/2 + j

2. 稀疏矩阵

非零元素极少且分布无规律的矩阵(如多数元素为0的系数矩阵),采用三元组表存储:

  • 每个非零元素用 (行标, 列标, 值) 表示;
  • 再存储矩阵的行数、列数和非零元素个数。

示例:矩阵 [[1,0,0],[0,2,0],[0,0,3]] 的三元组表为:
((0,0,1), (1,1,2), (2,2,3)),行数3,列数3,非零元素数3。

🌐 五,广义表

(一)广义表的定义

广义表(Lists)是线性表的扩展,允许元素既可以是单个数据(原子),也可以是另一个广义表(子表)。

  • 记为 LS = (a₁, a₂, ..., aₙ),n为长度,n=0时称为空表。
  • 示例:
    • A = ():空表,长度0;
    • B = (e):长度1,元素为原子e;
    • C = (a, (b, c, d)):长度2,第一个元素为原子a,第二个元素为子表 (b,c,d)
    • D = (A, B, C):长度3,元素均为子表。

广义表的深度是指嵌套的最大层数(空表深度为1),例如C的深度为2,D的深度为3。

(二)广义表的存储结构

由于元素可能是原子或子表,需用链式存储,每个节点包含标志位(区分原子或子表):

typedef enum {ATOM, LIST} ElemTag;  // ATOM=0表示原子,LIST=1表示子表
typedef struct GLNode {ElemTag tag;  // 标志位union {       // 共用体,原子或子表二选一char atom;                // 原子值(若tag=ATOM)struct GLNode *hp;        // 子表头指针(若tag=LIST)};struct GLNode *tp;  // 指向下一个元素(同层下一个节点)
} GLNode, *GList;

示例:广义表 C = (a, (b, c)) 的存储结构:

  • 头节点 tag=LIST,hp 指向第一个元素(原子a);
  • 原子a的节点 tag=ATOM,atom=‘a’,tp 指向第二个元素(子表);
  • 子表节点 tag=LIST,hp 指向子表 (b,c) 的头节点,tp=NULL(无下一个元素)。

🛠️ 案例分析与实现

案例:文本查找与替换工具

功能需求:实现一个简单的文本处理工具,支持在长文本中查找指定单词,并将所有匹配的单词替换为新单词(如将“数据结构”替换为“Data Structure”)。

核心思路

  1. 数据存储:使用堆分配串存储主文本(文章)、模式串(待查找单词)和替换串(新单词),支持动态调整长度;
  2. 查找逻辑:基于BF模式匹配算法,遍历主文本定位所有模式串的起始位置;
  3. 替换逻辑:对每个匹配位置,先删除原模式串,再插入替换串,更新主文本长度和内容。

完整代码实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 堆分配串定义
typedef struct {char *ch;      // 动态字符数组int length;    // 串实际长度
} HString;// 初始化串
void InitString(HString *s) {s->ch = NULL;s->length = 0;
}// 串赋值(将字符串常量复制到串中)
void StrAssign(HString *s, const char *chars) {if (s->ch) free(s->ch);  // 释放原有空间int len = strlen(chars);if (len == 0) {s->ch = NULL;s->length = 0;} else {s->ch = (char*)malloc((len + 1) * sizeof(char));  // +1预留结束符strcpy(s->ch, chars);s->length = len;}
}// BF模式匹配算法(返回模式串在主串中从pos开始的首次位置,1-based)
int IndexBF(HString S, HString T, int pos) {if (pos < 1 || pos > S.length || T.length == 0) return 0;  // 参数合法性检查int i = pos - 1;  // 主串下标(0-based)int j = 0;        // 模式串下标(0-based)while (i < S.length && j < T.length) {if (S.ch[i] == T.ch[j]) {i++;  // 匹配成功,继续比较下一个字符j++;} else {i = i - j + 1;  // 主串回溯到上一次匹配的下一位j = 0;          // 模式串重置到起点}}if (j == T.length) return i - T.length + 1;  // 匹配成功,返回1-based起始位置else return 0;  // 匹配失败
}// 替换主串中所有非重叠的模式串为替换串
void StrReplace(HString *S, HString T, HString V) {if (T.length == 0) return;  // 模式串为空,无需替换int pos = 1;  // 从主串第1个字符开始查找while (pos <= S->length - T.length + 1) {int i = IndexBF(*S, T, pos);  // 查找模式串位置if (i == 0) break;  // 未找到更多匹配,退出循环// 步骤1:删除主串中从i开始的模式串int delete_len = T.length;for (int j = i + delete_len - 1; j < S->length; j++) {S->ch[j - delete_len] = S->ch[j];  // 元素左移覆盖}S->length -= delete_len;  // 更新主串长度// 步骤2:在删除位置插入替换串int insert_len = V.length;if (insert_len > 0) {// 重新分配内存以容纳插入的字符S->ch = (char*)realloc(S->ch, (S->length + insert_len + 1) * sizeof(char));// 元素右移腾出插入空间for (int j = S->length - 1; j >= i - 1; j--) {S->ch[j + insert_len] = S->ch[j];}// 插入替换串内容for (int j = 0; j < insert_len; j++) {S->ch[i - 1 + j] = V.ch[j];}S->length += insert_len;  // 更新主串长度}// 下一次查找从替换后的下一个位置开始pos = i + insert_len;}
}int main() {HString text, oldWord, newWord;InitString(&text);InitString(&oldWord);InitString(&newWord);// 初始化文本、待替换单词和新单词StrAssign(&text, "数据结构是计算机科学的核心,学好数据结构很重要!");StrAssign(&oldWord, "数据结构");StrAssign(&newWord, "Data Structure");// 执行替换操作StrReplace(&text, oldWord, newWord);// 输出结果printf("替换后的文本:%s\n", text.ch); // 预期输出:"Data Structure是计算机科学的核心,学好Data Structure很重要!"// 释放内存free(text.ch);free(oldWord.ch);free(newWord.ch);return 0;
}

代码说明

  • 存储选择:堆分配串解决了定长串的长度限制问题,适合处理未知长度的文本;
  • 效率权衡:BF算法实现简单,适合短文本或模式串场景;若处理长篇小说等大文本,可优化为KMP算法提升效率;
  • 替换逻辑:通过“先删除后插入”的方式实现替换,需注意内存重分配和字符移位的边界处理。

📝 章结

串、数组和广义表是线性表的扩展与变形,在数据处理中承担着不同角色:

  • 作为字符的有序序列,是文本处理的基础。其核心价值在于模式匹配算法——从朴素的BF算法到高效的KMP算法,优化的不仅是时间复杂度,更是对“避免重复比较”这一思想的体现。存储结构的选择(定长、堆分配、链式)需结合文本长度和操作频率,例如堆分配串兼顾灵活性与访问效率,适合多数文本场景。

  • 数组通过多维下标实现结构化数据的存储,其顺序存储特性确保了高效的随机访问。特殊矩阵的压缩存储(如对称矩阵、稀疏矩阵)则展示了“按需存储”的优化思想——通过减少冗余数据,显著降低空间开销,这在科学计算、图像处理等领域至关重要。

  • 广义表打破了线性表的同质性限制,允许元素嵌套,是处理复杂层次数据的工具。其链式存储结构灵活支持原子与子表的混合存储,在Lisp等函数式语言、XML/JSON解析等场景中广泛应用。

从本质上看,这些结构都是对“数据关系”的抽象:串强调字符的顺序关系,数组强调多维索引关系,广义表强调嵌套关系。理解它们的存储规律和核心算法,不仅能解决具体问题,更能培养“根据数据特性选择结构”的思维——这正是数据结构的核心素养。

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

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

相关文章

服务器路由相关配置Linux和Windows

服务器路由相关配置Linux和Windowscentos路由系统核心概念传统工具集(命令)iproute2 工具集&#xff08;推荐&#xff09;NetworkManager 工具路由配置文件体系高级路由功能策略路由多路径路由路由监控工具系统级路由配置启用IP转发路由守护进程路由问题诊断流程Windows 路由Wi…

Spring Boot启动事件详解:类型、监听与实战应用

1. Spring Boot启动事件概述1.1 什么是Spring Boot启动事件在Spring Boot的应用生命周期中&#xff0c;从main方法执行到应用完全就绪&#xff0c;期间会发生一系列事件&#xff08;Event&#xff09;。这些事件由Spring Boot框架在特定时间点触发&#xff0c;用于通知系统当前…

Python闭包详解:理解闭包与可变类型和不可变类型的关系

一、定义闭包&#xff08;Closure&#xff09; 指的是一个函数对象&#xff0c;即使其外部作用域的变量已经不存在了&#xff0c;仍然能访问这些变量。简单来说&#xff0c;闭包是由函数及其相关的环境变量组成的实体。def outer():x 10def inner():print(x)return innerf ou…

BotCash:GPT-5发布观察 工程优化的进步,还是技术突破的瓶颈?

BotCash&#xff1a;GPT-5发布观察 工程优化的进步&#xff0c;还是技术突破的瓶颈&#xff1f; 在GPT-4以多模态能力震撼业界的一年后&#xff0c;GPT-5的亮相显得有些“平静”。当人们期待着又一场颠覆性技术革命时&#xff0c;这场发布会更像是给大模型技术按下了“精细打磨…

AJAX学习(2)

目录 一.XMLHttpRequest 二.XMLHttpRequest——查询参数 三.案例——地区查询 四.XMLHttpRequest_数据提交 五.Promise 六.Promise三种状态 七.PromiseeeXHR获取省份列表&#xff08;案例&#xff09; 八.封装-简易axios-获取省份列表 九.封装-简易axios-获取地区列表 …

解决 pip 安装包时出现的 ReadTimeoutError 方法 1: 临时使用镜像源(单次安装)

解决 pip 安装包时出现的 ReadTimeoutError 当您在使用 pip 安装 Python 包时遇到 pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(hostfiles.pythonhosted.org, port443): Read timed out. 错误时&#xff0c;这通常是由于网络问题导致的连接超时。P…

Linux下使用Samba 客户端访问 Samba 服务器的配置(Ubuntu Debian)

在 Linux 系统中&#xff0c;Samba 提供了与 Windows 系统文件共享的便利方式。本文将详细介绍在 Ubuntu 和 Debian 系统下如何安装 Samba 客户端、访问共享资源&#xff0c;并实现远程目录挂载和开机自动挂载。 文章参考自&#xff08;感谢分享&#xff09;&#xff1a;https…

解决dedecms文章默认关键字太短的问题

在管理文章或软件的时候&#xff0c;大家在添加关键字和内容摘要的时候&#xff0c;是不是对这样的情况感到比较的郁闷&#xff0c;我的关键字设定的明明非常的好&#xff0c;可是添加或修改后&#xff0c;会被无缘无故的截去很多&#xff0c;想必大家也都非常的明白&#xff0…

K8s-kubernetes(二)资源限制-详细介绍

K8s如何合理规定对象资源使用 基本概念 Kubernetes中&#xff0c;占用资源的最小单元为单个PodKubernetes中&#xff0c;资源占用主要针对服务器的CPU、内存 为什么要做资源限制 对于Kubernetes集群而言&#xff0c;所有Pod都会占用K8s集群所在服务器的资源&#xff0c;如果不做…

量子神经网络:从NISQ困境到逻辑比特革命的破局之路

——解析2025千比特时代开发者的机遇与行动框架 引言:量子计算的“20比特魔咒”与千比特悖论 当开发者被建议“避免在>20量子比特电路训练”时,富士通却宣布2025年实现10,000物理比特系统。这一矛盾揭示了量子计算从NISQ时代向FTQC时代跃迁的核心逻辑:千比特突破非为直接…

react+vite-plugin-react-router-generator自动化生成路由

前言&#xff1a;react项目实际使用中有很多提升性能与功能的插件&#xff0c;今天来说一说vite里面提供的vite-plugin-react-router-generator&#xff0c;他主要提供了自动生成路由的功能&#xff0c;配合我们的loadable/component可以实现路由的懒加载与统一管理。1、实现效…

服务器查看 GPU 占用情况的方法

在 Linux 系统中查看 GPU 占用情况&#xff0c;主要取决于你的 GPU 类型&#xff08;NVIDIA/AMD&#xff09;&#xff0c;以下是常用方法&#xff1a; 一、NVIDIA GPU&#xff08;最常用&#xff0c;如 RTX 系列、Tesla 系列&#xff09; 使用 NVIDIA 官方工具 nvidia-smi&…

【Docker实战进阶】Docker 实战命令大全

Docker 实战命令大全 Docker 实战场景&#xff0c;以 Nginx 为核心示例&#xff0c;梳理容器生命周期、镜像管理、网络配置、数据持久化及 Compose 编排的核心命令与最佳实践。 一、容器生命周期管理 1. 基础生命周期命令 docker run - 创建并启动容器 核心功能&#xff1a;基于…

PyCharm 2025.2:面向工程师的 AI 工具

引言 随着人工智能技术的快速发展&#xff0c;AI 工程师对开发工具的需求也在不断提升。PyCharm 2025.2 版本带来了革命性的 AI 工具包&#xff0c;将 AI 开发所需的实验、调试、评估和部署功能原生集成到 IDE 中。这一重大更新不仅提升了开发效率&#xff0c;也为 AI 工程师提…

爬虫逆向--Day15--核心逆向案例2(Python逆向实现请求加密、请求堆栈、拦截器关键字)

一、逆向案例之Python逆向实现请求加密//具体代码如下 function l(t, e) {return t.toString().toUpperCase() > e.toString().toUpperCase() ? 1 : t.toString().toUpperCase() e.toString().toUpperCase() ? 0 : -1}function u(t) {for (var e Object.keys(t).sort(l)…

时序数据库市场前景分析

1. 引言随着物联网&#xff08;IoT&#xff09;、工业互联网、金融科技、智慧城市等领域的快速发展&#xff0c;数据呈现爆发式增长&#xff0c;其中时间序列数据&#xff08;Time-Series Data&#xff09;占据了重要地位。时序数据库&#xff08;Time-Series Database, TSDB&a…

【网络安全测试】Burp Suite使用指导、配置及常见问题介绍(有关必回)

Burp Suite 是**渗透测试领域事实上的标准工具**&#xff0c;尤其擅长Web应用与API安全测试。针对AI系统&#xff0c;它主要用于测试模型API、管理后台等Web接口。以下是专业级使用指南&#xff1a;---### **一、 核心模块与功能概览**| **模块** | **核心功能** | **AI测试重点…

iOS 26 一键登录失效:三大运营商 SDK 无法正常获取手机号

近期&#xff0c;不少开发者和用户反馈&#xff0c;在升级到 iOS 26 系统后&#xff0c;App 内的 一键登录功能无法正常使用。无论是移动、电信还是联通的 SDK&#xff0c;都会出现无法获取手机号的情况&#xff0c;导致用户需要改用短信验证码或手动输入手机号完成登录。问题现…

OpenLayers与Vue.js结合实现前端地图应用

OpenLayers与Vue.js结合实现前端地图应用 下面我将为您展示如何将OpenLayers与Vue.js结合创建一个功能丰富的前端地图应用。这个教程包含了基础地图展示、标记点、地图控件以及交互功能。 实现结果 实现思路 在Vue项目中集成OpenLayers库创建基础地图视图和OSM图层添加标记点…

VisDrone数据集,专为无人机视觉任务打造

在农业巡查、环保监测、安防布控等广阔天地&#xff0c;无人机&#xff08;UAV&#xff09;早已超越了“拍照打卡”的酷炫标签&#xff0c;成为不可或缺的智能之眼。然而&#xff0c;当计算机视觉模型从地面“抬头”望向无人机视角时&#xff0c;迎接它的却是截然不同的挑战&am…