开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情
数据结构
第四章
第一节 串
串的定义
- 串:由零个或多个任意字符组成的有序数列,是内容受限(只能是字符类型)的线性表。
s="a1a2a3...an"(n>=0)
s是串名 "a1a2a3...an"是串值 n是串长 n=0是空串(空串用空集符号表示)
- 子串:一个串中任意连续字符组成的子序列称为子串。
例如:串 "abcde"的子串有: "","a","ab","abc","abcd","abcde". 真子串不包括串本身的所有子串。
- 包含多个子串的串称为主串。
字符位置:字符在序列中的序号为该字符在串的位置。
子串位置:子串第一个字符在主串中的位置。
例如:字符串 a,b,c,d
a="JING";
b="DONG";
c="JINGDONG";
d="JING DONG";
a字串在c中的位置是1,b字串在c中的位置是4;
c的长度是8,d的长度是9;
- 空格串:由一个或多个空格组成的串。(所有空串都是相等的)
- 串相等:当两个长度相等并且每个位置的字符都相等的情况下,两个串是相等的。
案例引入
串可以用于文字编辑、符号处理、各种信息处理系统等等。
比如以下的病毒感染检测,利用字符匹配来判断患者是否感染病毒。假设某种病毒序列是baa,由于病毒DNA序列是环状的,因此当前病毒序列有三种形式:baa,aba,aab,只要这三种序列形式满足一种与病人DNA匹配,就代表感染了。
串的类型定义和存储结构
抽象数据类型定义
存储结构
串的元素逻辑和线性表是相同的,因此串可以和线性表采用相同的存储结构
串的顺序存储结构
- 串的顺序存储结构类型定义
#define MAXLEN 255
typedef struct{
char ch[MAXLEN];
int length;
}String;
串的链式存储结构
优点:操作方便。缺点:存储密度低。 例如上面的存储密度,节点的数据域的存储大小为1个字节,指针域为4个字节,因此节点的存储密度为1/(1+4)=0.2=20%,存储密度低(存储密度低代表着空间利用率低)。 因此,可以存放多个字符在节点中,克服这个缺点
- 类型定义
#define MAXSIZE 80
typedef struct Chunk{
char ch[MAXSIZE];//字符数组
struct Chunk *next;
}Chunk;
typedef struct{
Chunk *head,*tail;//串的头指针和尾指针
int length;//串的长度
}LString;
串的模式匹配算法
算法目的:
确定主串所含子串(模式串)第一次出现的位置
算法应用
- 搜索引擎、拼写检查、语言翻译、数据压缩 算法种类
- BF算法:(Brute-Force,又称古典的、经典的、朴素的)。
- 也叫做简单匹配法。采用子串与主串的每个字符依次比较的方式来判断子串在主串是否匹配。
- KMP算法(速度快)。
BF算法实现模式匹配
定义类型
#include <stdio.h>
#include <malloc.h>
#define MAXLEN 255
typedef struct{
char ch[MAXLEN];
int length;
}String;
模式匹配
void match(String *str1,String *str2){
int i,j;
i=j=0;
while(i<str1->length&&j<str2->length){
//只要有一个串结束,整个循环就结束
if(str1->ch[i]==str2->ch[j]){//如果当前位置str1的字符和str2的字符匹配就都往后移动一个位置
i++;
j++;
}else{//如果主串中和子串的字符有一个不匹配,就让主串位置重新回到初始位置的后一个
i=i-j+1;
j=0;
}
}
if(j>str2->length-1){//如果子串的位置已经走到了最后,说明当前子串已经匹配上了
printf("匹配成功");
}else{
printf("匹配失败");
}
}
初始化并运行
int main(){
String str1,str2;
str1.ch[0]='a';
str1.ch[1]='b';
str1.ch[2]='c';
str1.ch[3]='c';
str1.ch[4]='d';
str1.ch[5]='e';
str1.length=6;
str2.ch[0]='b';
str2.ch[1]='c';
str2.ch[2]='c';
str2.ch[3]='d';
str2.length=4;
match(&str1,&str2);
}