数据结构-----串(String)详解

目录

前言

1.串的定义

相关类型

2.串的储存结构

顺序储存表示

堆分配储存表示

块链储存表示

3.串的操作方式

4.串的匹配算法

(1)BF算法

过程原理 

代码实现(C/C++) 

算法分析

(2)KMP算法

过程原理

匹配过程: 

 获取next数组:

代码实现(C/C++)

算法分析


前言

        前面我们学习了顺序表和线性表,这两种数据结构的储存数据域可以是一个任意类型,比如:整形、字符串类型、含有多种类型的结构体等等……那今天我们学习新的数据结构--串,其数据域的类型只能是字符类型,下面就一起来看看吧!

1.串的定义

  • 是由零个多个字符数组组成的有限序列。
  • 串中字符的个数称为串的长度,含有零个元素的叫空串。
  • 串是限定了元素为字符的线性表

(注:串与一般的线性表操作有很大区别,线性表主要针对表内的某个元素,而串操作主要针对子串

相关类型

  • :0个或多个字符组成的有限序列。S=′a1​a2​...an′​(n>=0)。
  • 串的长度:串中字符的个数
  • 空串:长度为0的串
  • 空格串:0个或多个空格字符组成的串
  • 子串:串中任意连续字符组成的子序列
  • 主串:包含子串的串
  • 位置:字符在串中的序号。ps:子串在主串中的位置是其第一个字符在主串中的位置。
  • 串的相等:长度和对应位置字符都相等

2.串的储存结构

顺序储存表示

 顺序储存结构是通过用一个连续地址的区域去储存字符数据,实际上就是数组的形式去储存。顺序储存方式必须去规定好最大储存值,储存的数量不能超过规定的最大值,超过的部分就要被舍去。顺序储存结构如下所示:

#define Maxsize 256//定义最大容量
//顺序储存
typedef struct string {char ch[Maxsize];//储存字符串int length;		//当前串的长度
}String;

堆分配储存表示

 堆分配储存方式是通过空间的动态分配内存来去储存数据的,然后通过指针域把堆里面分配好的不连续空间给链接到一起,形成链表。虽然是动态分配可以根据实际情况去分配容量,但是由于指针域占用4个字节的空间,然而数据域仅仅只占用1个字节空间,这就会有点浪费空间,所以很多时候我们会去用顺序储存方式来去实现一个串。堆分配储存结构如下所示:

typedef struct string {char ch;	//数据域struct string* next;//指针域
}String;

块链储存表示

 块链的储存结构是对堆分配储存方式的改进,就是提高了数据域的空间占用比,提高空间的利用率,一个节点可以去存放多个字符,如下所示:

3.串的操作方式

以下就是对字符串的操作方法,跟我们前面所学的顺序表和链表的操作方法基本上没有太大区别,这里我就不去一一详细讲了,有兴趣的小伙伴可以去自己把代码写完整实现这些功能。 

StrAssign(&T, chars);// 赋值操作。把串T赋值为 charsStrcopy(&T, S);// 复制操作。把串S复制得到串T。StrEmpty(S);// 判空操作。若S为空串, 则返回TRUE, 否则返回 FALSEReplace(&S, T, V);//串的替换操作,把T替换为VStrCompare(S, T);// 串比较操作。若S > T, 则返回值 > 0; 若S = T, 则返回值 = 0; 若S < T, 则返回值 < 0。StrEngth(S);// 求串长。返回串S的元素个数Substring(&Sub, S, pos, 1en);// 求子串。用Sub返回串S的第pos个字符起长度为len的子串。Concat(&T, S1, S2);// 串联接。用T返回由S1和S2联接而成的新串。StrInsert(&S, pos, T);//串的插入操作。把T插入到S的pos位置上Index(S, T);// 子串的定位操作。若主串S中存在与串T值相同的子串, 则返回它在主串S中第一次出现的位置; 否则函数值为0
Clearstring(&S);// 清空操作。将S清为空串Destroystring(&S);// 销毁串。将串S销毁

 下面我要重点讲的是字符串的查找匹配,也就是在一个主串中匹配里面是否有满足条件的子串,下面就来看看吧!

4.串的匹配算法

(1)BF算法

         BF算法,即暴力(Brute Force)算法,是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符与模式串T的第一个字符进行匹配,若相等,则继续比较S的第二个字符和 T的第二个字符;若不相等,则比较S的第二个字符和T的第一个字符,依次比较下去,直到得出最后的匹配结果。BF算法是一种蛮力算法

过程原理 
代码实现(C/C++) 
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#define Maxsize 256
//顺序储存
typedef struct string {char ch[Maxsize];//储存字符串int length;		//当前串的长度
}String;//01---串的模式匹配算法  暴力查找法
int Index_BF(String* S, String* T) {assert(S);assert(T);int i = 0, j = 0;while (i < S->length && j < T->length) {if (S->ch[i] == S->ch[i])	//当匹配到相同的时候{i++;		//主串和模式串的指针指向 依次+1j++;}else{i = i - j + 1;//主串回溯到后面一个字符j = 0;			//模式串回溯到第一个字符} }if (j == T->length)return i-j+2;	//返回匹配成功主串的位置return -1;
}
算法分析

 可以看出BF算法确实很暴力,一个一个去一一匹配,直到成功为止,所以时间复杂度为O(mn),m是主串的长度,n是模式串的长度

(2)KMP算法

        KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。

过程原理

 KMP算法可以很大限度减少匹配的次数,也就是说主串不需要去执行回溯的操作,从而提高匹配的效率,但是KMP算法还是有点难去理解的,需要用到一个next数组(可能失配位置),下面我会去详细说明的。

匹配过程: 

假设

主串:    a b c d a b e a b c d a b

模式串:a b c d a b d

第一次匹配 

a b c d a b e a b c d a b d

a b c d a b d

很明显第六个(d和e)出现了不同,在此之前前面出现相同的字符最大个数是2(分别是a、b)。

 第二次匹配

前面我们知道模式串出现相同字符最大个数为2,此时直接把子串相同字符的位置移动到以下位置:

a b c d a b e a b c d a b d

            a b c d a b d

这里我们可以发现主串跟模式串中的第三个字符不相匹配,所以此时要把模式串的第一个位置与 e 进行比较

第三次匹配

 a b c d a b e a b c d a b d

                   a b c d a b d

很显然此时模式串的第一个字符与主串不匹配,所以需要将主串的比较位置往后移动一位,模式串也是一样往后移动一位,再次比较

第四次匹配

 a b c d a b e a b c d a b d

                      a b c d a b d

此时匹配成功,返回主串匹配成功第一个字符的位置(主串中 a 的位置

 获取next数组:

对于模式串: a b c d a b d 

1.首位字符 a 前面是没有字符的,故没有前缀也没有后缀,那么其next数组值为-1,即next[ 0 ]=-1

2.对于第二个字符b 其前面的前缀和后缀都是字符a都是同一个,所以不能表示前缀与后缀相等,故其next数组值为0,即next[1]=0

3.对于第三个字符c其前面前缀a ,  b不相等,所以没有前缀与后缀相等,故next[2]=0

4.对于第四个字符d其前缀有a,ab,后缀有bc,c,故前缀与后缀都不相等,所以next[3]=0

5.对于第五个字符a其前缀有a,ab,abc后缀有bcd,cd,c同样也是不相等,所以next[4]=0

6.对于第六个字符b其前缀有a,ab,abc,abcd,后缀有bcda,cda,da,a,这里我们发现有一个前缀与后缀相等那就是 a 所以next[5]=1

7.对于第七个字符d其前缀有a,ab,abc,abcd,abcda,后缀有bcdab,cdab,dab,ab,a其相等的前缀和后缀一共有两个,所以next[6]=2

                               a          b           c             d          a            b        d 

                         next[0]    next[1]   next[2]   next[3]  next[4]  next[5]  next[6]

next数组的值:      -1            0            0             0        0            1           2

注意:next数组的值只跟模式串有关,与主串无关       

 下面给大家一个其他模式串的示例,你们也可以试着看怎么去求得next数组

代码实现(C/C++)
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#define Maxsize 256
//顺序储存
typedef struct string {char ch[Maxsize];//储存字符串int length;		//当前串的长度
}String;//02---串的模式匹配算法  KMP算法
//next 数组获取
int* Next(String* S) {assert(S);int* next = (int*)malloc(sizeof(int) * S->length);//开辟一个跟模式串一样长度的数组nextint j = -1, i = 0;	//初始化next[0] = -1;	//初始化while (i < S->length-1) {if (j == -1 || S->ch[i] == S->ch[j]) {	//当j为-1时候,也就是主串和模式串字符不匹配时;或者主串和模式串字符匹配的时候,进行next 数组赋值操作i++;j++;next[i] = j;	//如果不匹配的话,此时next数组当前的位置赋值为0,如果匹配的话就依次+1}else {j = next[j];	}}return next;
}//算法接口
int Index_KMP(String* S, String* T) {assert(S);assert(T);int i = 0, j = 0;int* next = Next(&T);while (i < S->length && j < T->length) {if (S->ch[i] == S->ch[i]){i++;j++;}else{//这里对比与BF算法,就少了主串i的回溯j = next[j];	//模式串j就直接移到next数组当前的位置}}if (j == T->length)return i - j + 2;return -1;
}
算法分析

可以看出相较于BF算法,KMP算法大大提高了匹配效率,时间复杂度为O(m+n),m为主串长度,n为模式串长度

以上就是本期的全部内容,你们学会了吗?我们下一期再见咯!

分享一张壁纸:

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

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

相关文章

红米note13 秒解锁BL 跳过168 秒解锁BL,红米Redmi Note 13 Pro+ 系列 无需等待168小时,刷入magisk教程 刷机包下载

最近入手了一台红米note13&#xff0c;发现需要等待168小时才能解锁BL&#xff0c;这让我感到非常困扰。不过&#xff0c;经过一番研究&#xff0c;我发现了一个秒解锁BL的方法&#xff0c;无需等待168小时&#xff0c;而且还可以刷入magisk&#xff0c;非常方便。 首先&#x…

【NetEQ】读 《白话解读 WebRTC 音频 NetEQ 及优化实践》学习笔记

白话解读 WebRTC 音频 NetEQ 及优化实践webrtc 的重要模块 官方文档 :转载请标明出处:大神翻译 大神地址 : https://blog.csdn.net/lhl_blog/article/details/10993605GIPS NetEQ概述 GIPS NetEQ是一项专为IP电信系统开发的高级语音质量处理技术,其能够在大幅提高语音质量的…

【Ubuntu18.04】Autoware.ai安装

Autoware.ai安装 1 ROS安装2 Ubuntu18.04安装Qt5.14.23 安装GCC、G4 Autoware安装与编译4.1 针对Ubuntu 18.04 / Melodic的依赖包安装4.2 Autoware环境搭建4.3 运行 Autoware4.4 ROSBAG Demo 1 ROS安装 参考笔者的博客即可&#xff1a;【ROS】Ubuntu18.04安装Ros 2 Ubuntu18.…

mock.js与组件通信之总线的讲解

目录 一Mock.js 1.1简介 1.2 安装配置Mock.js 1.3 mock.js的使用 二. 组件通信之总线 2.1 总线的简介 2.2 总线的使用-以导航栏的收进为例 好啦今天的分享就到这啦&#xff01;&#xff01; 一Mock.js 1.1简介 Mock.js 是一个用于生成随机数据的 JavaScript 库。它可以模拟…

蓄水池抽样算法

题目&#xff1a;在一个源源不断的数据流中&#xff0c;会吐出带有编号的球&#xff0c;现在问你 在不知道具体有多少个球的情况下&#xff0c;如何等概率的抽出10个球&#xff1f; 例题&#xff1a;leetcode 382题 应用场景&#xff1a;比如在某个游戏的抽奖活动中&#xff…

vue点击pdf文件直接在浏览器中预览文件

好久没有更新文章了&#xff0c;说说为什么会有这篇文章呢&#xff0c;其实是应某个热线评论的要求出的&#xff0c;不过由于最近很长一段时间没打开csdn现在才看到&#xff0c;所以才会导致到现在才出。 先来看看封装完这个预览方法的使用&#xff0c;主打一个方便使用&#x…

Purple-Pi-OH Linux SDK编译手册

一、 SDK下载 1.1 源码下载 在官网下载Purple-Pi-OH的的相关资料以及Linux SDK&#xff1a; 链接&#xff1a;Purple Pi OH-深圳触觉智能科技有限公司 1.2 源码解压 由于SDK打包后体积较大&#xff0c;我们在上传到百度云盘前把SDK包按照4GB大小分割了&#xff0c;因此下载…

基于物联网的农村地区智能微电网系统(Simulink)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

肖sir__mysql中数据库后端无法展示

mysql中数据库后端无法展示&#xff1a; 错误现象 解决方法&#xff1a; mysql中数据库后端无法展示&#xff1a;my.cnf (5,7数据库) 在 mysql 配置文件中加入&#xff1a; sql_modeNO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES 或者重启数据库

Mac配置iTerm样式终端

一、MacOs系统 MacOs中终端使用iTerm2 1. 配置oh-my-zsh oh my zsh 的地址&#xff1a; https//github.com/ohmyzsh/ohmyzsh 插件存放位置&#xff1a;~/.oh-my-zsh/plugins 下载常用的插件 git clone http://github.com/zsh-users/zsh-syntax-highlighting.git 修改配…

STC15F104W控制3个74HC595芯片输出数码管显示

一、74HC595脚位图及说明 管脚说明&#xff1a; 14脚&#xff1a;DS&#xff08;SER&#xff09;&#xff0c;串行数据输入引脚 13脚&#xff1a;OE&#xff0c;输出使能控制脚&#xff0c;它是低电才使能输出&#xff0c;所以接GND 12脚&#xff1a;RCK&#xff08;STCP&…

基于SpringBoot的可以做毕设或者课设的实时聊天系统(仿微信)

技术栈 前后端分离前端使用: Vue Element后端使用: SpringBoot Mysql8.0 Mybatis WebSocket 功能 登录和注册页 登录 和 注册 修改个人信息页 修改个人信息 消息列表页 展示最近半年的聊天信息&#xff0c;删除聊天记录 搜索好友和群页 搜索JJ号来找到 群/好友 好友信息详情页…

【app篇】写个简单的BLE调试app,练练手,同时为后续调试ESP32 BLE做个支持

忘记过去&#xff0c;超越自己 ❤️ 博客主页 单片机菜鸟哥&#xff0c;一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2023-09-25 ❤️❤️ 本篇更新记录 2023-09-25 ❤️&#x1f389; 欢迎关注 &#x1f50e;点赞 &#x1f44d;收藏 ⭐️留言&#x1f4dd;&#x1f64…

前端VUE---JS实现数据的模糊搜索

实现背景 因为后端实现人员列表返回&#xff0c;每次返回的数据量在100以内&#xff0c;要求前端自己进行模糊搜索 页面实现 因为是实时更新数据的&#xff0c;就不需要搜索和重置按钮了 代码 HTML <el-dialogtitle"团队人员详情":visible.sync"centerDi…

odoo16 取消“系统各功能状态日报”的邮件

odoo16默认情况下每周都会发送一个“系统各功能状态日报”的邮件&#xff0c;而且是所有人都发&#xff0c; 这个功能在哪配置呢&#xff1f; 今天研究了一下&#xff0c; 线索是“系统各功能状态日报”&#xff0c;先全文检索吧 #. module: digest #: model:digest.digest,na…

视频如何压缩?视频压缩到100M以内这样做

在日常生活中&#xff0c;我们常常需要处理各种各样的视频文件&#xff0c;但往往视频的大小会给我们的存储和传输带来困扰。那么&#xff0c;如何有效地压缩视频呢&#xff1f;下面就给大家分享三种解决方法&#xff0c;一起来看看吧。 方法一&#xff1a;嗨格式压缩大师 这是…

【flutter】架构之商城main入口

架构之商城main入口 前言一、项目模块的划分二、入口main的配置三、配置文件怎么做总结 前言 本栏目我们将完成一个商城项目的架构搭建&#xff0c;并完善中间的所有功能&#xff0c;总页面大概200个&#xff0c;如果你能看完整个栏目&#xff0c;你肯定能独立完成flutter 项目…

全流程ARCGIS Pro技术应用教程

详情点击公众号链接&#xff1a;全流程ARCGIS Pro技术应用教程 前沿 GIS是利用电子计算机及其外部设备&#xff0c;采集、存储、分析和描述整个或部分地球表面与空间信息系统。简单地讲&#xff0c;它是在一定的地域内&#xff0c;将地理空间信息和 一些与该地域地理信息相关…

基于springboot+vue的大学生竞赛交流系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

【内网穿透】在Ubuntu搭建Web小游戏网站,并将其发布到公网访问

目录 前言 1. 本地环境服务搭建 2. 局域网测试访问 3. 内网穿透 3.1 ubuntu本地安装cpolar 3.2 创建隧道 3.3 测试公网访问 4. 配置固定二级子域名 4.1 保留一个二级子域名 4.2 配置二级子域名 4.3 测试访问公网固定二级子域名 前言 网&#xff1a;我们通常说的是互…