数据结构中的串(String):概念、操作和实际应用

目录

一.引言

二.串的定义 

三. 串的抽象数据类型(ADT)

四. 串的存储结构

顺序存储结构

链式存储结构

五. 串模式的存储算法

KMP算法(Knuth-Morris-Pratt算法)

2.Brute-Force(暴力匹配)算法

3.Boyer-Moore算法

4.Rabin-Karp算法

六. 实际案例以及应用

七.总结


一.引言

        在计算机科学中,数据结构是一种用于组织和存储数据的方式。其中,串(String)是一种非常常见的数据结构,用于表示一组字符序列。串通常用于处理文本数据,如文本编辑器、搜索引擎、数据库系统等。在本文中,我们将深入探讨串的概念、操作以及实际应用。

二.串的定义 

        在计算机科学中,串 是由零个或多个字符组成的有限序列,是数据结构中常见的一种基本类型。它可以为空串,也可以是由字符组成的非空串。串通常用于表示文本数据,如文件内容、用户输入等,因此在算法和程序设计中占据着重要的地位。

        一个串可以是由字母、数字、符号等任意字符组成,字符的种类和个数没有固定限制。例如,"Hello, World!"、"123456"、"!@#$%" 都是串的例子。

        串的重要性在于它是对文本数据进行处理和操作的基础,涉及字符串匹配、文本编辑、编译器设计等多个领域。因此,深入理解串的特性和操作对于程序设计人员至关重要。

三. 串的抽象数据类型(ADT)

        在计算机科学中,为了方便对串进行操作和管理,可以定义串的抽象数据类型(ADT),以提供一组操作和属性来描述串的特性。下面是串的抽象数据类型的定义

// 串的抽象数据类型定义
typedef struct {char *str;  // 存储串的字符数组int length; // 串的长度
} String;

        在这个抽象数据类型中,str是一个指向字符数组的指针,用于存储串的内容,length表示串的长度。通过这个抽象数据类型,我们可以方便地对串进行创建、销毁、获取长度等操作,从而实现对串的高效管理和处理。

四. 串的存储结构

        串的存储结构是指如何在计算机内存中存储串的数据以及相关信息。常见的存储结构有两种:顺序存储结构和链式存储结构。下面分别介绍这两种存储方式,并给出相应的代码实现。

顺序存储结构

        顺序存储结构是将串中的字符顺序地存放在一段连续的存储空间中,通常是字符数组。下面是顺序存储结构的定义:

#define MAX_SIZE 100 // 假设串的最大长度为100typedef struct {char str[MAX_SIZE]; // 用字符数组存储串int length;         // 串的长度
} SeqString;

        在顺序存储结构中,str是一个字符数组,用于存储串的内容,length表示串的长度。通过这种方式,可以直接访问串中的任意字符,并且可以快速获取串的长度。

链式存储结构

        链式存储结构是通过链表来存储串的字符,每个节点存储一个字符,并且通过指针将各个节点连接起来。下面是链式存储结构的定义:

typedef struct LNode {char data;struct LNode *next;
} LNode;typedef struct {LNode *head; // 头指针int length;  // 串的长度
} LinkString;

        在链式存储结构中,每个节点中的data存储一个字符,next指针指向下一个节点。头指针head指向链表的第一个节点,通过遍历链表可以获取串的全部字符。链式存储结构适合于不确定串长度的情况,但需要额外的指针开销。

五. 串模式的存储算法

        串模式的存储算法主要用于实现串的模式匹配,下面是串模式常用的几种存储算法:

1.KMP算法(Knuth-Morris-Pratt算法)

  • KMP算法是一种高效的字符串匹配算法,通过预处理模式串,利用模式串中的信息在匹配失败时尽可能地减少比较次数,从而提高匹配效率。
  • KMP算法的核心思想是利用模式串内部的信息,在匹配失败时根据已匹配的部分,选择合适的位置进行模式串的移动。
  • 算法的关键在于部分匹配表(Next数组),它记录了模式串每个位置之前的子串中有多大长度的相同前缀和后缀。
  • 匹配过程中,当文本串的某个字符与模式串的对应字符不匹配时,利用Next数组确定模式串的移动位置,从而减少不必要的比较。

特点与应用:

  • KMP算法的时间复杂度为O(n+m),其中n为文本串的长度,m为模式串的长度。在实际应用中,KMP算法通常比暴力匹配算法具有更高的效率。
  • 由于其高效的匹配速度,KMP算法被广泛应用于字符串匹配、文本搜索、编译器设计等领域。
  • 在处理大规模文本数据时,KMP算法能够提供更快速和可靠的匹配方案,因此被视为处理字符串匹配问题的重要工具之一。

下面是KMP算法的核心部分:

void getNext(char *pattern, int next[]) {int len = strlen(pattern);next[0] = -1;int k = -1, j = 0;while (j < len - 1) {if (k == -1 || pattern[j] == pattern[k]) {++k;++j;next[j] = k;} else {k = next[k];}}
}int KMP(char *text, char *pattern) {int len1 = strlen(text);int len2 = strlen(pattern);int i = 0, j = 0;int *next = (int *)malloc(sizeof(int) * len2);getNext(pattern, next);while (i < len1 && j < len2) {if (j == -1 || text[i] == pattern[j]) {++i;++j;} else {j = next[j];}}free(next);if (j == len2) {return i - j; // 匹配成功,返回模式串在文本串中的起始位置} else {return -1; // 匹配失败}
}

2.Brute-Force(暴力匹配)算法

  • 暴力匹配算法是一种简单直接的字符串匹配算法,也称为朴素字符串匹配算法。它的基本思想是从文本串的第一个字符开始,与模式串进行逐个字符比较,若匹配失败,则将模式串右移一位,继续比较,直到找到匹配或者文本串被遍历完为止。
  • 该算法的时间复杂度为O(n*m),其中n为文本串的长度,m为模式串的长度。

以下是暴力匹配算法的核心部分的伪代码表示:

BruteForceSearch(text, pattern):n = 文本串的长度m = 模式串的长度for i from 0 to n - m do:j = 0while j < m 且 text[i + j] == pattern[j] do:j = j + 1if j == m:  # 找到了匹配返回 i  # 返回匹配位置的起始下标返回 -1  # 没有找到匹配

3.Boyer-Moore算法

  • Boyer-Moore算法是一种高效的字符串匹配算法,其核心思想是利用模式串中的字符出现位置的信息,在匹配失败时尽可能地跳过多的字符,从而减少比较次数。
  • 该算法包含两个启发式规则:坏字符规则和好后缀规则,通过这两个规则可以确定每次匹配失败时模式串的移动位置。
  • Boyer-Moore算法的时间复杂度在最坏情况下为O(n*m),但通常情况下具有线性时间复杂度。

以下是Boyer-Moore算法的核心部分的伪代码表示:

BoyerMooreSearch(text, pattern):n = 文本串的长度m = 模式串的长度lastOccurrence = 记录模式串中每个字符最后出现位置的数组suffix = 计算模式串的后缀数组prefix = 计算模式串的前缀数组初始化lastOccurrence数组,记录模式串中每个字符最后出现的位置初始化suffix数组,计算模式串的后缀数组初始化prefix数组,计算模式串的前缀数组i = m - 1  # 文本串中与模式串最后一个字符对齐的位置j = m - 1  # 模式串中最后一个字符的下标while i < n do:if text[i] == pattern[j]:  # 逐个字符比较if j == 0:  # 如果模式串已经比较完毕,说明找到了匹配返回 i  # 返回匹配位置的起始下标else:i = i - 1  # 继续向前比较j = j - 1else:badCharacterShift = j - lastOccurrence[text[i]]  # 坏字符规则计算位移goodSuffixShift = calculateGoodSuffixShift(j, suffix, prefix)  # 好后缀规则计算位移i = i + max(badCharacterShift, goodSuffixShift)  # 取较大的位移j = m - 1  # 重新比较模式串的最后一个字符返回 -1  # 没有找到匹配calculateGoodSuffixShift(j, suffix, prefix):k = m - 1 - j  # 好后缀的长度if suffix[k] != -1:  # 如果找到匹配的好后缀return j - suffix[k] + 1else:  # 如果找不到匹配的好后缀for r from j + 2 to m - 1:if prefix[m - r]:return rreturn m  # # 如果没有好后缀匹配,则移动整个模式串长度

4.Rabin-Karp算法

  • Rabin-Karp算法是一种基于哈希的字符串匹配算法,它通过对文本串和模式串进行哈希计算,然后比较它们的哈希值来判断是否匹配。
  • 该算法的优势在于可以在O(n+m)的时间复杂度内完成匹配,且在某些情况下比其他算法更加高效。
  • 然而,Rabin-Karp算法的实现涉及到哈希函数的设计和哈希冲突的处理,因此需要谨慎选择哈希函数以及解决哈希冲突的方法。

以下是Rabin-Karp算法的核心部分的伪代码表示:

RabinKarpSearch(text, pattern):n = 文本串的长度m = 模式串的长度p = 一个较大的素数,用于哈希计算textHash = 计算文本串text[0:m]的哈希值patternHash = 计算模式串pattern的哈希值for i from 0 to n - m do:if textHash == patternHash 且 text[i:i+m] == pattern:  # 判断哈希值相等且子串相等返回 i  # 返回匹配位置的起始下标if i < n - m:  # 更新下一次文本串的哈希值textHash = 重新计算text[i+1:i+m+1]的哈希值返回 -1  # 没有找到匹配

六. 实际案例以及应用

        串在计算机科学中有着广泛的应用,比如字符串匹配、文本编辑器、编译器等领域。

下面我们以文本编辑器为例进行说明。

首先,我们需要定义一些常量和全局变量:

#define MAX_LENGTH 1000char text[MAX_LENGTH];
int length = 0;

MAX_LENGTH 是文本的最大长度,text 是用于存储文本的字符数组,length 是当前文本的长度。

然后,我们定义一些函数来实现文本编辑器的功能:

void insert(int pos, char *str) {int len = strlen(str);if (length + len > MAX_LENGTH) {printf("Error: Text is too long\n");return;}for (int i = length; i >= pos; i--) {text[i + len] = text[i];}for (int i = 0; i < len; i++) {text[pos + i] = str[i];}length += len;
}void delete(int pos, int len) {if (pos + len > length) {printf("Error: Invalid position or length\n");return;}for (int i = pos; i < length - len; i++) {text[i] = text[i + len];}length -= len;
}void replace(int pos, int len, char *str) {delete(pos, len);insert(pos, str);
}int find(char *str) {int i, j, k;for (i = 0; i <= length - strlen(str); i++) {for (j = i, k = 0; text[j] == str[k]; j++, k++) {if (str[k + 1] == '\0') {return i;}}}return -1;
}

        insert 函数用于在指定位置插入一个字符串,delete 函数用于删除指定位置的字符串,replace 函数用于替换指定位置的字符串,find 函数用于查找指定的字符串。

        最后,我们编写主函数来测试这些函数:

int main() {insert(0, "Hello, ");insert(7, "World!");printf("Text: %s\n", text);replace(7, 5, "Dear");printf("Text: %s\n", text);int pos = find("Dear");if (pos != -1) {printf("Substring 'Dear' found at position %d\n", pos);} else {printf("Substring 'Dear' not found\n");}return 0;
}
运行这段代码,你将看到以下输出:Text: Hello, World!
Text: Hello, Dear!
Substring 'Dear' found at position 7

七.总结

        串是一种非常常见的数据结构,用于表示一组字符序列。它支持多种操作,如插入、删除、替换、查找、比较和连接。串在现实生活中有许多应用,如文本编辑器、搜索引擎、数据库系统和编译器等。

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

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

相关文章

Unity进阶之ScriptableObject

目录 ScriptableObject 概述ScriptableObject数据文件的创建数据文件的使用非持久数据让其真正意义上的持久ScriptableObject的应用配置数据复用数据数据带来的多态行为单例模式化的获取数据 ScriptableObject 概述 ScriptableObject是什么 ScriptableObject是Unity提供的一个…

有没有电脑桌面监控软件|十大电脑屏幕监控软件超全盘点!

电脑桌面监控软件已经成为许多领域不可或缺的工具。 无论是企业为了保障数据安全和提高工作效率&#xff0c;还是家长为了监督孩子的学习&#xff0c;甚至是个人为了记录电脑使用行为&#xff0c;都需要这类软件的支持。 本文将对市面上十大电脑屏幕监控软件进行超全盘点&…

智能文案生成器,文案生成改写很强大

在当今数字化时代&#xff0c;随着人工智能的迅猛发展&#xff0c;智能文案生成器正逐渐成为营销和创作领域的一大利器。这些智能工具不仅能够快速生成文案&#xff0c;还能够进行文案改写&#xff0c;使得文案生成的过程更加高效、便捷。正是在这样的背景下&#xff0c;智能文…

CAT:contig稳健物种分类

安装 mamba create -n CAT python3.10 diamond prodigal cd SoftWare git clone https://github.com/MGXlab/CAT_pack chmod 755 给权限 自己构建数据库 names.dmp nodes.dmp文件可以在Kraken2的文件里面找到 Kraken2Bracken&#xff1a;宏基因组物种注释_kracken2配合bracke…

MySQL之binlog归档日志

binlog&#xff08;二进制归档日志&#xff09; binlog 二进制日志记录保存所有执行过的修改操作语句&#xff0c;不保存查询操作。如果 MySQL 服务意外停止&#xff0c;可通过二进制日志文件排查&#xff0c;用户操作或表结构操作&#xff0c;从而来恢复数据库数据。启动 bin…

Java 线程的几种状态

一、 线程的状态 状态是针对当前的线程调度的情况来描述的。因为线程是调度的基本单位&#xff0c;所以状态更应该是线程的属性。在Java中线程的状态一共有六种&#xff1a; 1. 初始(NEW)&#xff1a;新创建了一个线程对象&#xff0c;但还没有调用start()方法。 2. 运行(RUNN…

动静态库以及动态链接

文章目录 静态库制作静态库如何使用静态库 动态库动态库的制作动态库的使用动态链接 库是给别人用的&#xff0c;所以库中一定不存在main函数。库一般会有lib前缀和后缀&#xff0c;去掉前缀和后缀才是库名。 静态库 静态库&#xff08;.a&#xff09;&#xff1a;程序在编译…

C++|对象与const

目录 常对象 常对象的声明 性质 数据成员不能被修改 常对象不能调用非const成员函数 const型成员函数 常对象成员 常数据成员 常成员函数 注意 总结 const型数据成员 const型成员函数 常对象 指针与const 指向对象的常指针 应用场景 指向常对象的指针 指向常…

Swagger3.0(Springdoc)日常使用记录

文章目录 前言一、默认地址二、注解OperationTag 三、SpringBoot基础配置四、Swagger导入apifox五、Swagger其他配置六 knife4j 参考文章 前言 本文并不是Swagger的使用教程&#xff0c;只是记录一下本人的操作&#xff0c;感兴趣的可以看下 一、默认地址 http://localhost:…

【1731】jsp 房租跟踪监控管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 房租跟踪监控管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysq…

Java 基础常见面试题整理

目录 1、java的基本数据类型有哪些&#xff1f;2、java为什么要有包装类型&#xff1f;3、String a "123" 和 String a new String("123") 区别&#xff1f;4、String、StringBuilder和StringBuffer的区别&#xff1f;5、如何理解面向对象和面向过程&…

浅谈叉车车载电脑的市场现状

叉车的起源 叉车源于美国&#xff0c;兴于日本&#xff0c;虽然中国起步较晚&#xff0c;但是近些年来发展迅速。叉车又称叉式装载车&#xff0c;是对于成件托盘类货物进行装卸、堆垛和短距离运输&#xff0c;实现重物搬运作业的轮式工业车辆。 叉车的分类 叉车分为以上六大类…

CSS学习(选择器、盒子模型)

1、CSS了解 CSS&#xff1a;层叠样式表&#xff0c;一种标记语言&#xff0c;用于给HTML结构设置样式。 样式&#xff1a;文字大小、背景颜色等 p标签内不能嵌套标题标签。 px是相对于分辨率而言的&#xff0c; em是相对于浏览器的默认字体&#xff0c; rem是相对于HTML根元…

刷题日记 ---- 顺序表与链表相关经典算法题(C语言版)

目录 1. 移除元素2. 合并两个有序数组3. 移除链表元素4. 反转链表5. 合并两个有序链表6. 链表的中间结点7. 环形链表的约瑟夫问题8. 分割链表总结 正文开始 1. 移除元素 题目链接: 移除元素 题目描述: 思路历程: 题目明确要求, 不能使用额外的数组空间, 也就是说不可以创建…

echarts之事件交互

ECharts 是一个优秀的开源可视化库&#xff0c;支持丰富的图表类型和交互功能。其中&#xff0c;事件交互是 ECharts 中非常重要的一部分&#xff0c;可以实现用户与图表的互动&#xff0c;比如点击、鼠标悬停等操作。下面我将为你介绍如何在 ECharts 中实现事件交互&#xff0…

Python基础学习之try

在Python编程中&#xff0c;异常处理是一种非常重要的编程技巧&#xff0c;它允许程序在运行时遇到错误或异常情况时能够优雅地处理&#xff0c;而不是直接崩溃。Python提供了try-except-finally结构来实现异常处理&#xff0c;使得程序能够在遇到错误时采取适当的措施&#xf…

【优质书籍推荐】AIGC时代的PyTorch 深度学习与企业级项目实战

大家好&#xff0c;我是herosunly。985院校硕士毕业&#xff0c;现担任算法研究员一职&#xff0c;热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名&#xff0c;CCF比赛第二名&#xff0c;科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的…

面:go能不能手写一个简单的协程池?

最简单的想法是使用chan管道和wg也就是sync.WaitGroup这两个搭档来进行实现协程池 那么在chan管道中最简单的就是无缓冲的了 对于协程池有啥操作&#xff1f; 第一个要想到newPool 并且要明白&#xff0c;这个协程池是不是你叫他停他才能停&#xff0c;如果没说&#xff0c…

springcloud按版本发布微服务达到不停机更新的效果

本文基于以下环境完成 spring-boot 2.3.2.RELEASEspring-cloud Hoxton.SR9spring-cloud-alibaba 2.2.6.RELEASEspring-cloud-starter-gateway 2.2.6.RELEASEspring-cloud-starter-loadbalancer 2.2.6.RELEASEnacos 2.0.3 一、思路 实现思路&#xff1a; 前端项目在请求后端接…

C++ 哈希

&#x1f493;博主CSDN主页:麻辣韭菜&#x1f493;   ⏩专栏分类&#xff1a;C知识分享⏪   &#x1f69a;代码仓库:C高阶&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多C知识   &#x1f51d;&#x1f51d; ​ 前言 1. unordered系列关联式容器 1.1 unor…