第4章串.docx

上传人:b****3 文档编号:2808084 上传时间:2022-11-15 格式:DOCX 页数:17 大小:96.88KB
下载 相关 举报
第4章串.docx_第1页
第1页 / 共17页
第4章串.docx_第2页
第2页 / 共17页
第4章串.docx_第3页
第3页 / 共17页
第4章串.docx_第4页
第4页 / 共17页
第4章串.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

第4章串.docx

《第4章串.docx》由会员分享,可在线阅读,更多相关《第4章串.docx(17页珍藏版)》请在冰豆网上搜索。

第4章串.docx

第4章串

第4章串

串(即字符串)是一种特殊的线性表,它的数据元素仅由一个字符组成,计算机非数值处理的对象经常是字符串数据,如在汇编和高级语言的编译程序中,源程序和目标程序都是字符串数据;在事物处理程序中,顾客的姓名、地址、货物的产地、名称等,一般也是作为字符串处理的。

另外串还具有自身的特性,常常把一个串作为一个整体来处理,因此,在这一章我们把串作为独立结构的概念加以研究,介绍串的存储结构及基本运算。

4.1串及其基本运算

4.1.1串的基本概念

⒈串的定义

串是由零个或多个任意字符组成的字符序列。

一般记作:

s=”a1a2…an””(4-1)

其中s是串名;在本书中,用双引号作为串的定界符,引号引起来的字符序列为串值,引号本身不属于串的内容;ai(1≤i≤n)是一个任意字符,它称为串的元素,是构成串的基本单位,i是它在整个串中的序号;n为串的长度,表示串中所包含的字符个数,当n=0时,称为空串,通常记为Ф。

⒉几个术语

子串与主串:

串中任意连续的字符组成的子序列称为该串的子串。

包含子串的串相应地称为主串。

子串的位置:

子串的第一个字符在主串中的序号称为子串的位置。

串相等:

是指两个串的长度相等且对应字符都相等。

4.1.2串的基本运算

串的运算有很多,下面介绍部分基本运算:

⒈StrLength(s):

求串长

操作结果是求出串s的长度。

⒉StrAssign(s1,s2):

串赋值

s1是一个串变量,s2或者是一个串常量,或者是一个串变量(通常s2是一个串常量时称为串赋值,是一个串变量称为串拷贝),操作结果是将s2的串值赋值给s1,s1原来的值被覆盖掉。

⒊StrConcat(s1,s2,s)或StrConcat(s1,s2):

连接操作

两个串的连接就是将一个串的串值紧接着放在另一个串的后面,连接成一个串。

前者是产生新串s,s1和s2不改变;后者是在s1的后面联接s2的串值成为s1串,s1改变,s2不改变。

例如:

s1=”he”,s2=”bei”,前者操作结果是s=”hebei”;后者操作结果是s1=”hebei”。

⒋SubStr(s,i,len):

求子串

串s存在并且1≤i≤StrLength(s),0≤len≤StrLength(s)-i+1。

操作结果是求得从串s的第i个字符开始的长度为len的子串。

len=0得到的是空串。

例如:

SubStr(”abcdefghi”,3,4)=”cdef”

⒌StrCmp(s1,s2):

串比较

操作结果是若s1==s2,操作返回值为0;

若s1

若s1>s2,返回值>0。

⒍StrIndex(s,t):

子串定位

s为主串,t为子串,操作结果是若t∈s,则操作返回t在s中首次出现的位置,否则返回值为0。

如:

StrIndex(”abcdebda”,”bc”)=2

StrIndex(”abcdebda”,”ba”)=0

⒎StrInsert(s,i,t):

串插入

串s,t存在,且1≤i≤StrLength(s)+1。

操作结果是将串t插入到串s的第i个字符位置上,s的串值发生改变。

⒏StrDelete(s,i,len):

串删除

串s存在,并且1≤i≤StrLength(s),0≤len≤StrLength(s)-i+1。

操作结果是删除串s中从第i个字符开始的长度为len的子串,s的串值改变。

⒐StrRep(s,t,r):

串替换

串s,t,r存在且t不为空,操作结果是用串r替换串s中出现的所有与串t相等的不重叠的子串,s的串值改变。

以上是串的几个基本操作。

其中前5个操作是最为基本的,它们不能用其他的操作来合成,因此通常将这5个基本操作称为最小操作集。

4.2串的定长顺序存储及基本运算

因为串是数据元素类型为字符型的线性表,所以线性表的存储方式仍适用于串,也因为字符的特殊性和字符串经常作为一个整体来处理的特点,串在存储时还有一些与一般线性表不同之处。

4.2.1串的定长顺序存储

类似于顺序表,用一组地址连续的存储单元存储串值中的字符序列,所谓定长是指按预定义的大小,为每一个串变量分配一个固定长度的存储区,如:

#defineMAXSIZE256

chars[MAXSIZE];

则串的最大长度不能超过256。

如何标识实际长度?

⒈类似顺序表,用一个指针来指向最后一个字符,这样表示的串描述如下:

typedefstruct{

chardata[MAXSIZE];

intcurlen;

}SeqString;

SeqStrings;//定义一个串变量

这种存储方式可以直接得到串的长度:

s.curlen+1。

如图4-1所示。

0

1

2

3

4

5

6

7

8

9

10

MAXSIZE-1

a

b

c

D

e

f

g

h

i

j

k

s.data

图4-1串的顺序存储方式1

⒉在串尾存储一个不会在串中出现的特殊字符作为串的终结符,以此表示串的结尾。

比如C语言中处理定长串的方法就是这样的,它是用’\0’来表示串的结束。

这种存储方法不能直接得到串的长度,是用判断当前字符是否是’\0’来确定串是否结束,从而求得串的长度。

chars[MAXSIZE];

0

1

2

3

4

5

6

7

8

9

10

MAXSIZE-1

a

b

c

d

e

f

g

h

i

j

k

\0

图4-2串的顺序存储方式2

⒊设定长串存储空间:

chars[MAXSIZE+1];用s[0]存放串的实际长度,串值存放在s[1]~s[MAXSIZE],字符的序号和存储位置一致,应用更为方便。

4.2.2定长顺序串的基本运算

本小节主要讨论定长串联接、求子串、串比较算法,顺序串的插入和删除等运算基本与顺序表相同,在此不在赘述。

串定位在下一小节讨论,设串结束用’\0’来标识。

⒈串联接

串连接是把两个串s1和s2首尾连接成一个新串s。

intStrConcat1(chars1[],chars2[],chars[]){

inti,j,len1,len2;

i=0;

len1=StrLength(s1);

len2=StrLength(s2)

if(len1+len2>MAXSIZE-1)

return0;//s长度不够

j=0;

while(s1[j]!

=’\0’)

{s[i]=s1[j];

i++;

j++;

}

j=0;

while(s2[j]!

=’\0’)

{s[i]=s2[j];

i++;

j++;

}

s[i]=’\0’;

return1;

}

【算法4-1】串连接算法

⒉求子串

intStrSub(char*t,char*s,inti,intlen){

//用t返回串s中第个i字符开始的长度为len的子串1≤i≤串长

intj;

intslen;

slen=StrLength(s);

if(i<1||i>slen||len<0||len>slen-i+1)

{cout<<”参数不对”<

return0;

}

for(j=0;j

t[j]=s[i+j-1];

t[j]=’\0’;

return1;

}

【算法4-2】求子串算法

⒊串比较

intStrComp(char*s1,char*s2){

inti=0;

while(s1[i]==s2[i]&&s1[i]!

=’\0’)

i++;

return(s1[i]-s2[i]);

}

【算法4-3】串比较算法

4.2.3模式匹配

串的模式匹配即子串定位是一种重要的串运算。

设s和t是给定的两个串,在主串s中查找子串t的过程称为模式匹配,如果在s中找到等于t的子串,则称匹配成功,函数返回t在s中的首次出现的存储位置(或序号),否则匹配失败,返回0。

t也称为模式。

为了运算方便,设字符串采用定长存储,且用第三种方式表示串长,即串的长度存放在0号单元,串值从1号单元存放,这样字符序号与存储位置一致。

⒈简单的模式匹配算法

算法思想如下:

首先将s1与t1进行比较,若不同,就将s2与t1进行比较,...,直到s的某一个字符si和t1相同,再将它们之后的字符进行比较,若也相同,则如此继续往下比较,当s的某一个字符si与t的字符tj不同时,则s返回到本趟开始字符的下一个字符,即si-j+2,t返回到t1,继续开始下一趟的比较,重复上述过程。

若t中的字符全部比完,则说明本趟匹配成功,本趟的起始位置是i-j+1或i-t[0],否则,匹配失败。

设主串s=“acabaabaabcacaabc”,模式t=“abaabcac”,匹配过程如图4-3所示。

依据这个思想,算法描述如下:

intStrIndex_BF(char*s,char*t){

//从串s的第一个字符开始找首次与串t相等的子串

inti,j;

i=1,j=1;

while(i<=s[0]&&j<=t[0])//都没遇到结束符

if(s[i]==t[j])

{i++;

j++;

}  //继续

else

{

i=i-j+2;

j=1;

}//回溯

if(j>t[0])

return(i-t[0]); //匹配成功,返回存储位置

else

return0;

}

【算法4-4】简单的模式匹配算法

 

 

该算法简称为BF算法。

下面分析它的时间复杂度,设串s长度为n,串t长度为m。

匹配成功的情况下,考虑两种极端情况:

⑴在最好情况下,每趟不成功的匹配都发生在第一对字符比较时:

例如:

s=”aaaaaaaaaabc”

t=”bc”

设匹配成功发生在si处,则字符比较次数在前面i-1趟匹配中共比较了i-1次,第i趟成功的匹配共比较了m次,所以总共比较了i-1+m次,所有匹配成功的可能共有n-m+1种,设从si开始与t串匹配成功的概率为pi,在等概率情况下pi=1/(n-m+1),因此最好情况下平均比较的次数是:

即最好情况下的时间复杂度是O(n+m)。

⑵在最坏情况下,每趟不成功的匹配都发生在t的最后一个字符:

例如:

s=”aaaaaaaaaaab”

t=”aaab”

设匹配成功发生在si处,则在前面i-1趟匹配中共比较了(i-1)*m次,第i趟成功的匹配共比较了m次,所以总共比较了i*m次,因此最坏好情况下平均比较的次数是:

 

即最坏情况下的时间复杂度是O(n*m)。

上述算法中匹配是从s串的第一个字符开始的,有时算法要求从指定位置开始,这时算法的参数表中要加一个位置参数pos:

StrIndex(shar*s,intpos,char*t),比较的初始位置定位在pos处。

算法4-4是pos=1的情况。

⒉改进后的模式匹配算法

BF算法简单但效率较低,一种对BF算法做了很大改进的模式匹配算法是克努特(Knuth)、莫里斯(Morris)和普拉特(Pratt)同时发现的,简称KMP算法。

⑴KMP算法的思想

分析算法4-4的执行过程,造成BF算法速度慢的原因是回溯,即在某趟的匹配过程失败后,对于s串要回到本趟开始字符的下一个字符,t串要回到第一个字符。

而这些回溯并不是必要的。

如图4-3所示的匹配过程,在第三趟匹配过程

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1