数据结构之串

串:是由零个或多个字符组成的有限序列,又名字符串。

串的比较是通过组成串的字符之间的编码来进行的,而字符的编码指的是字符在对应字符集中的序号

给定两个串s=“a1a2。。。。。an” t=“b1b2。。。。。。bm”当满足以下条件之一时 s<t.

1.n<m 且ai=bi(i=1,2。。。。,n)

例如s=“hap” t=“happy” 因为t比s多出2个字符 所以s<t

2.存在某个k<=min(m,n) 使的ai=bi(i=1,2。。。。。。,k-1),ak<bk

例如当s=“happen” t=“happy” 因为两串的前4个字符相同 第5个字母(k值),字母e的ASCLL码是101,而字母y的ASCLL码是121 显然e<y 所以s<t。

串的抽象数据类型

ADT 串 (string)

Data

串中元素仅由一个字符组成,相邻元素具有前驱和后继关系

Operation

StrAssign(T,*chars):生成一个其值等于字符串常量chars的串T

StrCopy(T,S):串S存在,由串S赋值得串T

ClearString(S):串S存在,将串清空。

StringEmpty(S):若串S为空,返回true,否则返回false

StrLength(S):返回串S的元素个数,即串的长度

StrCompare(S,T):若S>T,返回值>0,若S=T 返回0,若S<T,返回值<0

Concat(T,S1,S2):用T返回由S1和S2联接而成的新串。

SubString(Sub,S,pos,len):串S存在,1<=pos<=StrLength(S),且                                               0<=len<=StrLength(S)-pos+1,用Sub返回串S的                                               第pos个字符起长度为len的子串。

Index(S,T,pos):串S和T存在,T是非空串,1<=pos<=StrLength(S),若主串S中                                  存在和串T值相同的子串,则返回它在主串S中第pos个字符之后第                                  一次出现的位置,否则返回0

Replace(S,T,V):串S,T和V存在,T是非空串,用V替换主串S中出现的所有与T相等                                  的不重叠的子串

StrInsert(S,pos,T):串S和T存在,1<=pos<=StrLength(S)+1.在串S的第pos个                                  字符之前插入串T

StrDelete(S,pos,len):串S存在,1<=pos<=StrLength(S)-len+1。从串S中删                                  除第pos个字符起长度为len个子串

endADT

Index实现算法

T为非空串,若主串S中第pos个字符之后存在与T相等的子串

则返回第一个这样的子串在S中的位置,否则返回0

int Index(String S,String T,int pos)

{

int n,m,i;

String sub;

if(pos > 0)

{

n = StrLength(S);   得到主串S的长度

m = StrLength(T);   得到子串T的长度

i = pos;

while(i <= n-m+1)

{

SubString(sub,S,i,m); 取主串第i个位置 长度与T相等子串给sub

if(StrCompare(sub,T) != 0)  如果两串不相等

++i;

else    如果两串相等

return i;           则返回i值

}

}

return 0;   若无子串与T相等 返回0

}

串的顺序存储结构

串的顺序存储结构是用一组地址连续的存储单元来存储串中的字符序列的。按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区。一般是用定长数组。\0来表示串值的终结。

串的链式存储结构

一个结点可以存放一个字符或者多个字符,最后一个结点若是未被占满时,可以用#或其他非串值补全

模式匹配:子串的定位操作

对主串的每一个字符作为子串开头,与要匹配的字符串进行匹配。

假设主串S和要匹配的子串T的长度存在S[0]与T[0]。

返回子串T在主串S中第pos个字符之后的位置,若不存在,则函数返回值为0.

T非空,1<=pos<=StrLength(S)。

int Index(String S,String T,int pos)

int i = pos;           i用于主串S中当前位置下标,若pos不为1。则从pos位置开始匹配

int j = 1;             j用于子串T中当前位置下标值

while(i<=S[0] && j <=T[0])      若i小于S长度且j小于T的长度时循环

if(S[i] == T[j])   两字母相等则继续

++i;

++j;

else                       指针后退重新开始匹配

i = i-j+2;         i退回到上次匹配首位的下一位

j = 1;             j退回到子串T的首位

if (j >T[0])

return i-T[0];

else

return 0;

时间复杂度O(n+m)

最坏的情况时间复杂度O((n-m)m)

KMP模式匹配算法

T=abcabx

j 123456

模式串T abcdex

next[j] 011111

1.当j=1时 next[1]=0;

2.当j=2时 j由1到j-1就只有字符a,属于其他情况next[2]=1;

3.当j=3时 j由1到j-1串是ab,显然a与b不相等,属其他情况,next[3]=1;

4.以后同理,所以最终此T串next[j]为011111

T=abcabx

j 123456

模式串T abcabx

next[j] 011123

1.当j=1  next[j]=0

2.当j=2  同上 next[2]=1

3.当j=3  同上 next[3]=1

4.当j=4  同上next[4]=1

5.当j=5  此时j由1到j-1的串是abca 前缀字符a与后缀字符a相等,因此可推算出k值为2因此next[5]=2;

6.当j=6  j由1到j-1的串是abcab,由于前缀字符ab与后缀ab相等所以next[6]=3

根据经验如果前一个字符相等,k值是2,2个相等,k值是3,n个,k值n+1

代码如下

通过计算返回子串T的next数组

void get_next(String T,int *next)

int i,j;

i=1;

j=0;

next[1]=0;

while(i<T[0])   此处T[0]表示串T的长度

if(j==0 || T[i]==T[j]) T[i]表示后缀的单个字符,T[j]表示前缀的单个字符

++i;

++j;

next[i]=j;

else

j=next[j]; 若字符不相同 则j值回溯

计算出当前要匹配的串T的next数组。

返回子串T在主串S中第pos个字符之后的位置,若不存在,则函数返回值为0

T非空1<=pos<=StrLength(S)

int Index_KMP(String S,String T,int pos)

int i=pos;    i用于主串S当前位置下标值,若pos不为1,则从pos位置开始匹配

int j=1;      j用于子串T中当前位置下标值

int next[255];

get_next(T,next); 定义一next数组

while(i <= S[0] && j<=T[0])若i小于S的长度且j小于T的长度时,循环继续

if(j==0 || S[i]==T[j]) 两字母相等则继续,与朴素算法增加。j=0判断

++i;

++j;

else            指针后退重新开始匹配

j=next[j];    j退回合适的位置  i值不变

if(j>T[0])

return i-T[0];

else

return 0;

KMP算法仅当模式与主串之间存在许多 部分匹配 的情况下才体现出它的优势

KMP模式匹配算法改进

求模式串T的next函数修正值并存入数组nextval

void get_nextval(String T,int *nextval)

int i,j;

i=1;

j=0;

nextval[1]=0;

while(i<T[0])

if(j==0 || T[i]==T[j])

++i;

++j;

if(T[i] != T[j])

nextval[i]=j;

else

nextval[i]=nextval[j];

else

j=nextval[j];

改良后对比

T=ababaaaba

j 123456789

模式串T ababaaaba

next[j] 011234223

nextval[j] 010104210

1.当j=1  nextval[1]=0

2.当j=2  因第2位字符b的next值是1,而第一位就是a,它们不相等,所以nextval[2]=next[2]=1 维持原值

3.当j=3  因为第三位字符a的next值为1,所以与第一位的a比较得知它们相等,所以nextval[3]=nextval[1]=0;

4.当j=4  第四位的字符b next值为2,所以与第二位的b相比较得到结果是相等,因此nextval[4]=nextval[2]=1

5.j=5  next值为3 第五个字符a 与第三个字符a 相等,因此nextval[5]=nextval[3]=0;

6.当j=6  next值为4 第六个字符a 与第四个字符b不相等,因此nextval[6]=4;

7.当j=7  next值为2, 第七个字符a 与第二个字符b不相等 因此nextval[7]=2

8.当j=8  next值为2,第八个字符b与第二个字符b相等  nextval[8]=nextval[2]=1

9.当j=9时  next值为3 第九个字符a 与第三个字符a 相等 nextval[9]=nextval[3]=1

是在计算出next值的同时,如果a位字符与它next值指向的b位字符相等,则该a位的nextval就指向b位的nextval值,如果不等,则该a位的nextval值就是它自己a位的next的值

时间: 2024-10-10 17:41:48

数据结构之串的相关文章

数据结构 顺序串笔记

/* 数据结构--串笔记 串:由零个或多个字符组成的有限序列. 串也有两种储存方式,顺序储存和链式储存 1.顺序表示的串--顺序串 一般使用字符型数组储存. 确定串的长度有两种方法.一是:在串的末尾加一个结束标记(在C语言 中系统自动在串值的末尾加一个'\0'作为结束标记 ),再使用 strlen 函数得到串的长度.二是:增加一个变量 len 用来储存串的长度. */ // 顺序串的实现即基本操作 # include <stdio.h> # include <stdlib.h> #

数据结构例程——串的模式匹配(KMP算法)

本文针对数据结构基础系列网络课程(4):串中第5课时串的模式匹配(KMP算法). 问题:串的模式匹配 KMP算法: #include <stdio.h> #include "sqString.h" void GetNext(SqString t,int next[]) /*由模式串t求出next值*/ { int j,k; j=0; k=-1; next[0]=-1; while (j<t.length-1) { if (k==-1 || t.data[j]==t.d

数据结构例程——串的顺序存储应用

本文针对数据结构基础系列网络课程(4):串中第3课时串的顺序存储应用. 例1:串比较 问题: 设计实现串比较运算的算法 算法思路 (1)比较s和t两个串共同长度范围内的对应字符: ① 若s的字符>t的字符,返回1: ② 若s的字符<t的字符,返回-1: ③ 若s的字符=t的字符,按上述规则继续比较. (2)当(1)中对应字符均相同时,比较s和t的长度: ① 两者相等时,返回0: ② s的长度>t的长度,返回1: ③ s的长度<t的长度,返回-1. #include <stdi

【数据结构】串的堆分配表示与实现

采用堆分配存储表示的串被称为堆串,与顺序串相比,地址空间仍是连续,但空间是在程序执行时动态分配的. 程序中会使用到的realloc函数: //realloc : (void *)reelloc (void *ptr,unsigned newsize); //使用 : char *str; //   str = (char *)realloc(str,20); 代码实现如下: <span style="font-size:18px;">#pragma once #includ

数据结构:串

一.串的基本概念 1.串的定义 s=“a1a2…an” 2.串的基本操作 二.串的顺序存储结构 1.串的非紧缩存储 一个存储单元中只存储一个字符,和顺序表中一个元素占用一个存储单元类似.具体形式见图1,设串S=“How do you do”. 2.串的紧缩存储 根据各机器字的长度,尽可能将多个字符存放在一个字中.假设一个字可存储4个字符,则紧缩存储具体形式. 3.串的字节存储 三.串的链式存储结构 1 ///Name:String 2 ///Author:JA 3 ///Date:2015-3-

【数据结构】-串

一.串的基本概念 串(字符串):是由零个或多个字符组成的有限序列,一般记为: s='a1a2-an'(n>=0) s是串名,单引号括起来的是串的值,ai(1<=i<=n)可以是字母.数字或其他字符. 串中字符的数目n称为串的长度: 长度为零的串称为空串: 串中任意个连续的字符组成的子序列称为子串: 包含子串的串相应的称为主串: 字符在序列中的序号称为该字符在串中的位置: 子串在主串中的位置以子串的第一个字符在主串中的位置来表示. 二.串的表示和实现 1)定长顺序存储表示:用一组地址连续的

数据结构之串及其模式匹配

这里说了些什么? 在这个章节讲了串的结构.构造串的方法.各种对串的操作以及从串的匹配的算法. 串的结构也是千奇百态,有直接按顺序存储的结构,有链条式的存储结构以及基于顺序存储结构和链条结构的合体的名字索引表. 串的操作有点像C++里面有个库叫sctring的操作,函数名字都一样的,然后就是告诉我们是怎么实现的. 模式匹配算法是传统的BF算法(一个一个比失败了就挪动一个位置继续比)和KMP算法(牛皮的跳跃式匹配).关于这个算法我做了一个ppt但是好像不好直接上传,我就上传到了百度云制作了一个链接,

数据结构8_串类型的定义、表示和实现

串类型的定义 串是由零个或多个字符组成的有限序列. 串中字符的数目n称为串的长度.零个字符的串称为空串. 串中任意个连续的字符组成的子序列称为该串的子串. 包含子串的串相应地称为主串.通常称字符在序列中的序号为该字符在串中的位置. 串值必须用一对单引号括起来.单引号本身不属于串,它的作用只是为了避免与变量名或数的常量混淆而已. 例如 x='123': x是一个串变量名,字符序列123是其值. 由一个或多个空格组成的串''称为空格串(注意不是空串). 串的逻辑结构和线性表极为相似,区别仅在于串的数

数据结构与算法合集

数据结构 [Java] 大话数据结构(1) 线性表之顺序存储结构 [Java] 大话数据结构(2) 线性表之单链表 [Java] 大话数据结构(3) 线性表之静态链表 [Java] 大话数据结构(4) 线性表之循环链表 [Java] 大话数据结构(5) 线性表之双向链表 [Java] 大话数据结构(6) 栈的顺序与链式存储 [Java] 大话数据结构(7) 循环队列和链队列 [Java] 大话数据结构(8) 串的模式匹配算法(朴素.KMP.改进算法) [Java] 大话数据结构(9) 树(二叉树