版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
5.1串及其运算5.2串的存储结构5.3串的模式匹配算法5.4多维数组5.5矩阵的压缩存储习题5第5章串和数组5.1.1串的概念
串(String)是由多个或零个字符组成的有限序列,记做S="c1c2c3…cn"(n≥0)。其中,S是串名;由双引号括起来的字符序列称为串值,但双引号本身不属于串;ci(1≤i≤n)是串中字符,i是字符在串中的位置序号;n是串的长度,表示串中字符的个数,不包含任何字符的串称为空串,例如""是长度为0的空串。5.1串 及 其 运 算串中任意个连续的字符组成的子序列称为该串的子串,包含子串的串相应地称为主串。子串在主串中的序号定义为子串在主串中首次出现的位置序号。例如,设S1和S2分别为
S1=“Thisisastring”S2=“is”
则S2是S1的子串,S1是S2的主串。S2在S1中出现了两次,首次出现在主串的第3个位置上,因此S2在S1中的序号是3。
特别需要一提的是,空串是任意串的子串,任意串是其自身的子串。通常,串可以分为串变量和串常量。正如我们所知道的,在程序中常量只能被引用而不能改变其值,但变量的值可以被改变。在C++语言中,串变量可以用字符型数组来表示,串常量可以用双引号括起来的字符序列直接表示或者用符号常量来表示,例如有如下定义:
charstr[]="string";constcharstr_const[]="string";
str是串变量,而str_const是串符号常量。5.1.2串的基本运算
串的基本运算和线性表有很大的差别。线性表的插入、删除等运算都是以“单个元素”作为操作对象;而对串的运算,通常是把串作为一个整体进行操作,如串的复制、串的比较、插入和删除子串等。
很多高级语言都提供了字符串操作的函数库,下面结合串的基本运算给出C语言有关字符串操作函数的例子。我们先定义几个相关的变量:
chars1[80]=“d:\\user\\wang\\”,s2[40]=“file.txt”,s3[80];//字符串中含有转义字符‘\\‘
intresult;
说明:字符串从字符数组下标为0的元素开始存放。例如:result=strcmp(“good”,“Good”); //result>0
result=strcmp(“15”,“15”); //result=0
result=strcmp(“That”,“The”); //result<0
(4) StrCat(&T,S)——串联接,将串S联接到串T的末尾,返回指向串S的指针。
例如:printf(“%s”,strcat(s1,s2));
//输出:d:\\user\\wang\\file.txt
(5) StrStr(S,Sub)——子串定位,查找串Sub在串S中第一次出现的位置,若查找到,则返回该位置信息,否则返回NULL。
例如:printf("%d\n",strstr(s1,"user")-s1+1);//输出4
(6) StrChr(S,C)——字符定位,查找字符C在串S中第一次出现的位置,若查找到,则返回该位置信息,否则返回NULL。
例如:result=strchr(s2,‘t’)-s2+1;//result的值是6
上述操作是最基本的串运算,其余的串运算一般可以由这些基本运算组合而成。
voidsubstr(char*sub,char*s,intpos,intlen)
{
if(pos<1||pos>strlen(s)||len<0)printf(“parametererror!\n”);
else{
strncpy(sub,s+pos-1,len); //复制子串字符
strcpy(sub+len,“\0”); //添加子串的串结束符
}
}
上述程序是C语言的完整程序。不同的语言对串运算会有差异,因此应以该语言的参考手册为准。5.2.1串的顺序存储
串的顺序存储结构简称为顺序串。与顺序表类似,顺序串是用字符向量来存储,并且在串的末尾用一个特定的字符作为串结束符,例如C语言中以转义字符‘\0’作为串结束符。为了具有一般性,我们仍然把串的类型定义为一个结构类型,其中用一个一维字符型数组存放串值,并用一个整型量表示串的长度。串的类型定义如下:
#definemaxsize256
typedefstruct
{charch[maxsize];
intlength;
}SeqString;5.2串的存储结构
【例5.2】
编写一个算法voidstrdelete(SeqString*S,intpos,intlen),若满足1≤pos≤S->length-len+1,则从串S中删除第pos个字符开始长度为len的子串;否则不删除。
voidstrdelete(SeqString*S,intpos,intlen)
{
chartemp[maxsize];
if(pos>=1&&pos<=S->length-len+1){
strncpy(temp,S->ch,pos-1);
strcpy(temp+pos-1,S->ch+pos+len-1);
strcpy(S->str,temp);
S->length=S->length-len;
}
}5.2.2串的链式存储
和顺序表类似,在顺序串上不方便进行插入、删除操作,需要移动大量的元素。采用链表存储串值可以提高插入、删除的效率,串的链式存储结构简称为链串。链串中的每个结点可以存放一个字符,若结点的指针域占4个字节,那么链串的存储密度只有20%。如果每个结点存放多个字符,例如4个字符,则存储密度可以达到50%,从而有效地提高了存储空间的利用率。通常将每个结点存放字符的个数定义为结点大小,图5.1(a)和(b)中的每个结点大小分别是1和4。一个结点可存放多个字符,而串长度不一定是结点大小的倍数,因此链表中最后一个结点的数据域有可能没有被串值占满,可以用特殊的字符(例如'\0')来填充。图5.1链串的示意图链串结点的类型定义如下:
(1)结点大小为1。
typedefstructnode
{chardata;
structnode*next;
}LinkString;
(2)结点大小为4。
typedefstructnode
{chardata[4];
structnode*next;
}LinkString;子串定位又称为串的模式匹配(PatternMatching),是串运算中最重要的操作之一。所谓模式匹配,就是在文本中查找是否存在给定的单词及出现的位置,例如实现文本编辑程序中的查找功能。C语言函数库中的子串定位函数strstr可以实现串的模式匹配操作,串的模式匹配算法分朴素的模式匹配和改进的模式匹配两种。5.3串的模式匹配算法5.3.1顺序串上的模式匹配
朴素的模式匹配算法又称为穷举的模式匹配算法,假设S为目标串(主串),T为模式串(子串),
S="s1,s2,…,sn"T="t1,t2,…,tm"其中0<m≤n
在实际应用中,模式串长度m通常远远小于目标串长度n,即m<<n。下面给出不依赖其他串操作运算的模式匹配算法。分别利用计数指针i和j指示目标串S和模式串T中当前比较的字符位序。算法的基本思想是:从目标串S的第pos个字符开始与模式串T的第一个字符进行比较,若相等,则继续比较后面的字符;否则,从目标串的下一个字符开始与模式串的第一个字符进行下一趟比较。重复此过程,直至模式串中的每个字符依次与目标串中的一个连续的字符序列相等,则匹配成功,函数值为与模式串中第一个字符相等的字符在目标串中的位序;如果各趟比较均不相等,则匹配不成功,函数值为0。从图5.2可以看出模式串T="abc"与目标串S="abbabca" 的匹配过程(pos=1)。图5.2朴素的模式匹配过程现在分析算法的时间复杂度。在最坏情况下,假设每一趟都比较了m次才能够确定对应的字符是否均相等,共匹配了n-m+1趟,比较字符的总次数为m(n-m+1),由于n>>m,因此时间复杂度是O(m*n)。朴素的模式匹配算法虽简单,但效率较低,这是因为在一趟匹配中目标串内可能存在多个和模式串“部分匹配”的子串,而引起计数指针i的多次回溯。一种改进的模式匹配算法的时间复杂度为O(m+n)。其改进在于:每当一趟过程中出现字符比较不等时,不需回溯i指针,而是利用已经得到的“部分匹配”的结果将模式串向右“滑动”尽可能远的距离,再继续进行比较。具体算法读者可参阅有关资料。5.3.2链串上的模式匹配
我们以结点大小为1的单链表存储串,实现朴素的模式匹配算法。在算法中使用指针shift指向每一趟在目标串中比较的起始位置,若一趟比较中出现不相等的字符,指针shift右移指向下一个结点,继续下一趟的比较。若匹配成功,则返回shift所指向的结点地址;若匹配不成功,则返回空地址值。具体算法如下:矩阵广泛用于科学计算与工程应用中,在用高级语言编写程序时,常常采用二维数组存储矩阵。采用这种存储方法时,不仅使矩阵运算简单,而且存储密度高。但是,如果阶数很高的矩阵中非零元素的分布具有一定的规律或者矩阵中有大量的零元素,则为了节省存储空间,可以对这类矩阵进行压缩存储。所谓压缩存储,就是为多个值相同的元素只分配一个存储空间,零元素不分配存储空间。5.5矩阵的压缩存储5.5.1特殊矩阵
特殊矩阵是指n阶方阵中非零元素或零元素的分布具有一定的规律。下面我们讨论几种特殊矩阵的压缩存储。
1.三角矩阵
在n阶方阵中,以主对角线划分,如果矩阵的下三角(不包括主对角线)中的元素均为值相同的常数,则称为上三角矩阵,反之称为下三角矩阵。在多数情况下,三角矩阵的常数为零。两种三角矩阵如图5.3所示。图5.3三角矩阵图5.4一个4阶对称方阵图5.5一个4阶对称方阵的压缩存储
3.对角矩阵
所谓对角矩阵,是指方阵中的所有非零元素集中在以主对角线为中心的带状区域内,带状区域之外的元素值均为零。带宽为3的对角矩阵又称为三对角矩阵,如图5.6所示。图5.6三对角矩阵将稀疏矩阵中的非零元素的行号、列号和元素值作为一个三元组(i,j,aij),所有非零元素的三元组按行优先(或列优先)的顺序排列(跳过零元素),则得到一个其结点均是三元组的线性表。我们将该线性表的顺序存储结构称为三元组表。在下面的讨论中,三元组均以按行优先的顺序进行排列。
在三元组表中除了要表示非零元素之外,还需表示矩阵的行数、列数及非零元素的总数。三元组表的结构类型定义描述为设a为spmattrix型指针变量,图5.7(a)所示的稀疏矩阵A的三元组表如图5.7(b)所示。
下面以矩阵的转置为例,说明采用三元组表的形式存储稀疏矩阵时,如何实现矩阵的运算。
一个m×n的矩阵A,它的转置矩阵B是一个n×m的矩阵,且A[i][j]=B[j][i],0≤i≤m-1,0≤j≤n,即A的行是B的列,A的列是B的行。例如,图5.7(a)中的A和图5.8(a)中的B互为转置矩阵。图5.7稀疏矩阵A和它的三元素表 *a图5.8稀疏矩阵B和它的三元素表 *b为了叙述方便,下面将三元组表*a中的成员a->data简称为三元组表,因为相对于其它成员而言,它是主要的。
将A转置为B,就是将A的三元组表a->data置换为B的三元组表b->data,如果只是互换a->data中i和j的内容,那么所得到的b->data是按列存放的矩阵B的三元组表,还必须重新排列b->data中各结点的顺序。由于A的列是B的行,故按a->data的列序转置,所得到的转置矩阵B的三元组表b->data必定是按行优先的顺序存放。算法的基本思想是:对a->data按列扫描n趟,在第col趟扫描中,找出所有列号等于col的那些三元组,将它们的行号、列号和元素值分别放入b->data的列号、行号和元素值中,即可得到B的按行优先的压缩存储表示。以图5.7和图5.8为例,设col=0,则扫描a->data找到列号为0的三元组依次是(0,0,3)和(2,0,2),存入b->data后为(0,0,3)和(0,2,2),恰好为B中第0行的两个非零元素,只要依次取col=0,1,2,3,即可得到a->data的转置矩阵b->data。下面给出具体的算法:该算法的时间主要耗费在col和ano的二重循环上,算法的时间复杂度为O(n×t)。而通常用二维数组表示矩阵时,其转置算法的时间复杂度是O(m×n)。如果非零元素个数大于矩阵的行数,则从转置算法的时间复杂度来说,采用三元组表存储就不合适了。
一、名词解释
串,顺序串,链串,特殊矩阵,稀疏矩阵,对称方阵,上(下)三角矩阵
二、填空题
1.含零个字符的串称为______串,用______表示。其他串称为______串。任何串中所含______的个数称为该串的长度。
2.当且仅当两个串的______相等并且各个对应位置上的字符都______时,这两个串相等。一个串中任意个连续字符组成的序列称为该串的______串,该串称为它所有子串的______串。习题5
3.通常将链串中每个存储结点所存储的字符个数称为______。当结点大小大于1时,链串的最后一个结点的各个数据域不一定总能全被字符占满,此时,应在这些未用的数据域里补上______。
4.一般地,一个n维数组可视为其数据元素为______维数组的线性表。数组通常只有______和_______两种基本运算。
5.通常采用_______存储结构来存放数组。对二维数组可有两种存储方法:一种是以______为主序的存储方式,另一种是以______为主序的存储方式。C语言数组用的是以______序为主序的存储方法。
6.数组M中每个元素的长度是3个字节,行下标i从1到8,列下标j从1到10,从首地址EA开始连续存放在存储器中。若按行方式存放,则元素M[8][5]的起始地址为_______;若按列优先方式存放,则元素M[8][5]的地址为_______。
7.二维数组M的成员是6个字符(每个字符占一个存储单元)组成的串,行下标i的范围从0到8,列下标j的范围从1到10,则存放M至少需要______个字节;M的第8列和第5行共占_______个字节;若M按行方式存储,元素M[8][5]的起始地址与当M按列优先方式存储时的_______元素的起始地址一致。
8.需要压缩存储的矩阵可分为_______矩阵和_______矩阵两种。
9.对称方阵中有近半的元素重复,若为每一对元素只分配一个存储空间,则可将n2个元素压缩存储到_______个元素的存储空间中。
10.假设以一维数组M(1..n(n+1)/2)作为n阶对称矩阵A的存储结构,以行序为主序存储其下三角(包括对角线)中的元素,数组M和矩阵A间对应的关系为_______。
11.上三角矩阵中,主对角线上的第t行(1≤t≤n)有_______个元素,按行优先顺序在一维数组M中存放上三角矩阵中的元素aij时,aij之前的前i-1行共有_______个元素,在第i行上,aij是该行的第_______个元素,M[k]和aij的对应关系是_______。当i>j时,aij=c(c表示常量),c存放在M[________]中。
三、选择题
1.在串的基本运算中,能够改变串值的运算有()。
A. EQAL(S,T) B. LENGTH(S)
C. CONCAT(S,T)
D. REPLACE(S,T,R)
E. INDEX(S,T)
2.在串的基本运算中,不能够改变串值的运算有()。
A. ASSIGN(S,T) B. INSERT(S1,i,S2)
C. DELETE(S,i,j)
D. SUBSTR(S,i,j)
E. REPLACE(S,T,R)
3.对于以行序为主序的存储结构来说,在数组A[c1..d1,c2..d2]中,c1和d1分别为数组A的第一个下标的下界和上界,c2和d2分别为第二个下标的下界和上界,每个数据元素占K个存储单元,二维数组中任一元素a[i,j]的存储位置可由()式确定。
A. Loc(i,j)=Loc(c1,c2)+[(i-c1)*(d2-c2)+(j-c2)]*k
B. Loc(i,j)=Loc(c1,c2)+[(i-c1)*(d2-c2+1)+(j-c2)]*k
C. Loc(i,j)=Loc(c1,c2)+[(j-c2)*(d1-c1+1)+(i-c1)]*k
D. Loc(i,j)=Loc(c1,c2)+[(j-c2)*(d1-c1)+(i-c1)]*k
4.对于C语言的二维数组DataTypeA[m][n],每个数据元素占K个存储单元,二维数组中任意元素a[i,j]的存储位置可由()式确定。
A. Loc(i,j)=Loc(0,0)+[i*(n+1)+j]*k
B. Loc(i,j)=Loc(0,0)+[j*(m+1)+i]*k
C. Loc(i,j)=Loc(0,0)+(i*n+j)*k
D. Loc(i,j)=Loc(0,0)+(j*m+i)*k
5.稀疏矩阵的压缩存储方法是只存储()。
A.非零元素 B.三元组(i,j,aij)
C. aij D. i,j
6.基于三元组表的稀疏矩阵,对每个非零元素aij,可以用一个()唯一确定。
A.非零元素B.三元组(i,j,aij) C. aijD. i,j
7.二维数组M[i,j]的元素是4个字符(每个字符占一个存储单元)组成的串,行下标i的范围从0到4,列下标j的范围从0到5。若M按行存储,元素M[3,5]的起始地址与M按列存储时,元素()的起始地址相同。
A. M[2,4] B. M[3,4] C. M[3,5] D. M[4,4]
8.常对数组进行的两种基本操作是()。
A.建立与删除 B.建立与修改
C.查找与修改 D.查找与索引四、问答及算法设计
1.简述下列各对术语的区别。
空串和空格串;串变量和串常量;主串和子串;串变量的名字与串变量的值
2.设有A=“”,B=“mule”,C=“old”,D=“my”,试计算下列运算的结果(注:A+B是CONCAT(A,B)的简写,A=“”表示含有两个空格的字符串)。
(a) A+B (b) B+A
(c) D+C+B
(d) SUBS
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论