第4章 串.docx
- 文档编号:4451716
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:32
- 大小:165.28KB
第4章 串.docx
《第4章 串.docx》由会员分享,可在线阅读,更多相关《第4章 串.docx(32页珍藏版)》请在冰豆网上搜索。
第4章串
第4章串
4.1串的基本概念
4.1.1串的定义4.1.2串的抽象数据类型4.1.3最小操作子集4.1.1串的定义
1.串2.主串与子串3.子串的定位4.串的比较5.空格串与空串6.串与线性表
1.串
串(String):
串是由n(n≥0)个字符组成的有限序列。
一般记为:
S=“a1a0…an”
其中:
S是串名;双引号括起来的字符序列是串的值;ai(1≤i≤n)可以是英文字母、数字字符或其他字符,其值均取自于某个字符集;串中字符的个数n称为串的长度;n为0时是空串。
2.主串与子串
⑴子串:
串中任意个连续的字符组成的子序列称为该串的子串。
空串是任何串的子串。
⑵主串:
包含子串的串称为主串。
⑶字符的定位:
一个字符在串中的序号称为该子符在串中的位置。
⑷真子串:
一个串S也可以看成是自身的子串,除本身之外的其他子串都称为真子串。
3.子串的定位
子串在主串中的位置指的是该子串的第一个字符在主串中第一次出现的位置。
4.串的比较
给定两个串:
X=“x1x2…xn”,Y=“y1y2…ym”,则:
当n=m且x1=y1,x2=y2,…,xn=ym时,称X=Y。
当下列条件之一成立时,称X ⑴n ⑵存在某个k≤min(m,n),使得xi=yi(i=1,2,…,k-1),xk 例如: s1=“child”;s2=“chalde”;s3=“student”;s4=“student”;则: s1>s2,s3 5.空格串与空串 空格串: 由一个或多个空格符组成的串串中包含空格符,串长不为0。 空串: 串长为0,即串中不包含任何字符。 6.串与线性表 串是一种数据元素固定为字符的线性表。 因此,仅就数据结构而言,串归属于线性表这种数据结构。 但是,串的基本操作和线性表上的基本操作相比却有很大的不同。 线性表上的操作主要是针对线性表中的某个数据元素进行的,而串上的操作则主要是针对串的整体或串的某一部分子串进行的。 4.1.2串的抽象数据类型 ADTString{ Data: 串中的数据元素仅由一个字符组成,相邻元素具有前驱和后继的关系。 Operation: StrAssign(&S,chars) 初始条件: chars是字符串常量。 操作结果: 把chars赋为串S的值。 StrCopy(&S,T) 初始条件: 串T存在。 操作结果: 由串T复制得串S。 StrEmpty(S) 初始条件: 串S存在。 操作结果: 若S为空串,则返回true;否则返回false。 StrLength(S) 初始条件: 串S存在。 操作结果: 返回S的元素个数,即串的长度。 StrCompare(S,T) 初始条件: 串S和T存在。 操作结果: 若S StrConcat(&S,T) 初始条件: 串S和T存在。 操作结果: 用S返回由S和T联接而成的新串。 SubString(S,&Sub,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值相同的子串,则由pos返回它在主串S中第一次出现的位置,函数值为true;否则函数值为false。 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的子串。 Replace(&S,T,V) 初始条件: 串S,T和V存在,T是非空串。 操作结果: 用V替换主串S中出现的所有与T相等的不重叠的子串。 StrTraveres_Sq(S) 初始条件: 串S已存在。 操作结果: 依次输出串S中的每个字符。 DestroyString(&S) 初始条件: 串S存在。 操作结果: 串S被撤销。 }ADTString。 4.1.3最小操作子集 对于串的基本操作集,可以有不同的定义方法,各种程序设计语言都有自己的串操作函数,如在表4.1中列出了C/C++部分串操作函数。 一般来说,串赋值StrAssign、串挎贝StrCopy、串比较StrCompare、求串长StrLength、串联接StrConcat以及求子串SubString等操作可以构成串结构的最小操作子集,即这些操作不能用其他串操作来实现,反之,其他串操作(除串撤销DestroyString外)均可在这个最小操作子集上实现。 如串置换操作就可通过调用串的定位操作、串插入操作和串删除操作来实现。 表4.1C/C++中对应的串操作函数 4.2顺序串及其操作 1.顺序串的定义2.顺序串的结构描述3.顺序串的基本操作4.C++中的串操作 1.顺序串的定义 串的顺序存储结构简称顺序串。 与顺序表类似,顺序串是用一组地址连续的存储单元来存储串中的字符序列。 因此可用高级语言的字符数组来实现,按其存储分配的不同可分为: 静态存储分配的顺序串和动态存储分配的顺序串。 2.顺序串的结构描述 ⑴静态存储分配的顺序串⑵动态存储分配的顺序串 ⑴静态存储分配的顺序串 直接使用定长的字符数组来定义: #defineMaxStrSize256 typedefcharSqString[MaxStrSize+1]; 类似静态顺序表的定义: typedefstruct{ charstr[MaxStrSize]; intlength; }SSqString; 说明: 静态存储分配的顺序串,都是用定长字符数组存储串值,串的操作比较简单,但由于串值空间的大小已经确定,所以对串的某些操作,如插入、连接、置换等带来不便。 ⑵动态存储分配的顺序串 在应用程序中,参与运算的串变量之间的长度相差较大,并且在操作中串值长度的变化也比较大,因此,可利用C/C++的函数malloc()为每个新产生的串分配一块实际串长所需的存储空间,并将其起始地址作为串的基址。 这样,当进行串的插入、连接等操作时,再根据实际需要增补空间,以满足插入和连接等操作的需要。 所以在描述动态顺序串时,当前数组的容量和增补空间量不再作为结构的一部分,其结构的描述如下: typedefstruct{ char*str;//存放非空串的首地址 intlength;//存放串的当前长度 }DSqString; 说明: 动态存储分配的顺序串,串值空间的大小是在程序执行时动态分配而得,这对串的插入、连接、置换等操作非常有利,因此在串处理的应用程序中也常被选用。 3.顺序串的基本操作 1.串赋值2.串复制3.求串长4.串比较5.串连接6.取子串7.子串的定位8.插入子串、 9.删除子串10.置换子串11.串的遍历12.撤销顺序串 1.串赋值 串赋值操作就是把一个字符串常量赋值给顺序串S。 其主要操作是: ①判断顺序串S是否非空,若是,则释放其空间; ②求串常量的长度,若长度等于0,就将顺序串S置空,否则,以此长度为标准为顺序串S申请空间; ③把串常量chars的值复制到顺序串S中去,同时顺序串S的长度被赋值为串常量的长度。 其算法描述见算法4.1。 可以利用这个操作进行顺序串的初始化。 算法4.1 boolStrAssign_Sq(DSqString&S,char*chars) { inti,j; char*c; if(! S.str)free(S.str); for(i=0,c=chars;*c;i++,c++); if(! i){S.str=NULL;S.length=0;} else{ if(! (S.str=(char*)malloc(i*sizeof(char)))) returnfalse; for(j=0;j S.str[j]=chars[j]; S.length=i; } returntrue; }//StrAssign_Sq 2.串复制 串复制操作就是把一个顺序串T复制到另一个顺序串S中,使S和T具有一样的串值。 其主要操作是: ①判断顺序串S是否非空,若是,则要释放顺序串S原有空间; ②判断顺序串T的长度T.length是否等于0,若是,就将顺序串S置空,否则,为顺序串S申请T.length个数据元素的空间 ③把顺序串T的值复制到顺序串S中去,同时顺序串S的长度被赋值为T.length。 其算法描述见算法4.2。 算法4.2 boolStrCopy_Sq(DSqString&S,DSqStringT) { inti; if(! S.str)free(S.str); if(! T.length){S.str=NULL;S.length=0;} else{ if(! (S.str=(char*)malloc(T.length*sizeof(char)))) returnfalse; for(i=0;i S.str[i]=T.str[i]; S.length=T.length; } returntrue; }//StrCopy_Sq 3.求串长 intStrLength_Sq(DSqStringS) { return(S.length); }//StrLength_Sq 4.串比较 比较顺序串S和顺序串T,若S 其主要操作是: 从顺序串S的第一个字符和顺序串T的第一个字符开始比较,若顺序串S的对应字符大于顺序串T的对应字符,则返回1;若顺序串S的对应字符小于顺序串T的对应字符,则返回-1;若顺序串S的对应字符等于顺序串T的对应字符,则循环继续比较下一对字符,直至对应字符不相等或顺序串S或顺序串T结束时循环终止。 若循环终止后: 顺序串S没有结束,则返回1;顺序串T没有结束,则返回-1;顺序串S和顺序串T同时结束则返回0。 其算法描述见算法4.4。 算法4.4 intStrCompare_Sq(DSqStringS,DSqStringT) {inti=0; while(i { if(S.str[i]>T.str[i])return1; elseif(S.str[i] i++; } if(i elseif(i return0; }//StrCompare_Sq 5.串连接 将顺序串T连接在顺序串S之后,并返回连接后的顺序串S。 其主要操作是: ①判断顺序串T的长度是否为非0,若是,则为顺序串S增补T.length个数据元素的空间; ②把顺序串T中的所有字符复制到顺序串S中去,同时将顺序串S的长度增加T.length。 其算法描述见算法4.5。 算法4.5 boolStrConcat_Sq(DSqString&S,DSqStringT) { inti; if(T.length){ if(! (S.str=(char*)realloc(S.str,(S.length+T.length)*sizeof(char)))) returnfalse; for(i=0;i S.str[S.length+i]=T.str[i]; S.length+=T.length; } returntrue; }//StrConcat_Sq 6.取子串 在顺序串S中从第pos个位置开始,取长度为len的子串Sub。 其主要操作是: ①判断取子串的位置pos和长度len是否合理,若不合理,则返回false,否则执行②; ②判断子串Sub是否非空,若是,则释放其空间,否则为子串Sub申请len个数据元素的空间; ③从主串第pos个位置开始复制len个字符到子串Sub中去,同时串Sub的长度被赋值为len。 其算法描述见算法4.6。 算法4.6 boolSubString_Sq(DSqStringS,DSqString&Sub,intpos,intlen) { inti; if(pos<0||pos>S.length-1||len<0||len>S.length-pos) returnfalse; if(Sub.str)free(Sub.str); if(! len){Sub.str=NULL;Sub.length=0;} else{ if(! (Sub.str=(char*)malloc(len*sizeof(char)))) returnfalse; for(i=0;i Sub.str[i]=S.str[pos+i]; Sub.length=len; } returntrue; }//SubString_Sq取子串操作过程演示 7.子串的定位 子串的定位操作也叫串查找操作、串的模式匹配操作。 它是在主串S中查找是否存在和串T值相同的子串,若存在,则匹配成功,并由pos返回它的第一个字符在主串S中第一次出现的位置,否则匹配失败。 其主要操作是: 将串S的第一个字符和串T的第一个字符进行比较,若相等,则继续比较两者的后续字符;否则,将串S的第二个字符和串T的第一个字符进行比较,重复上述过程,若串T中的字符全部比较完毕,则本趟匹配成功,函数返回true;否则返回false。 其算法描述见算法4.7。 算法4.7 boolIndex_Sq(DSqStringS,DSqStringT,int&pos) { inti=0,j=0; while(i {if(S.str[i]==T.str[j]) {i++;j++; } else {i=i-j+1; j=0; } } if(j==T.length){pos=i-T.length;returntrue;} elsereturnfalse; }//Index_Sq 8.插入子串 在顺序串S的第pos个字符之前插入子串T。 其主要操作是: ①判断插入的位置pos是否合理,若不合理,则返回false,否则执行②; ②判断子串T是否非空,若是,则为串S增补T.length个数据元素的空间; ③将串S中从pos位置开始到串结束之间的所有字符向后移动T.length个元素位置; ④把串T中的所有字符复制到顺序串S第pos至pos+T.length-1中去,同时顺序串S的长度增加T.length。 其算法描述见算法4.8。 算法4.8 boolStrInsert_Sq(DSqString&S,intpos,DSqStringT) { inti; if(pos<0||pos>S.length)returnfalse; if(T.str) { if(! (S.str=(char*)realloc(S.str,(S.length+T.length)*sizeof(char)))) returnfalse; for(i=S.length-1;i>=pos;i--) S.str[i+T.length]=S.str[i]; for(i=0;i S.str[pos+i]=T.str[i]; S.length=S.length+T.length; } returntrue; }//StrInsert_Sq插入子串操作过程演示 9.删除子串 从顺序串S的第pos个字符开始删除长度为len的子串。 其主要操作是: ①判断删除的位置pos和长度len是否合理,若不合理,则返回false,否则执行②; ②将串S中从pos+len位置开始到串结束之间所有字符向前移动len个元素的位置,同时串S的长度减少len; ③将串S的存储空间减少len。 其算法描述见算法4.9。 算法4.9 boolStrDelete_Sq(DSqString&S,intpos,intlen) { inti; if(pos<0||len<0||pos+len>S.length)returnfalse; for(i=pos+len;i<=S.length-1;i++) S.str[i-len]=S.str[i]; S.str=(char*)realloc(S.str,(S.length-len)*sizeof(char)); S.length=S.length-len; returntrue; }//StrDelete_Sq删除子串操作演示 10.置换子串 用串V置换主串S中出现的所有与T相等的不重叠子串。 其主要操作是: ①调用子串的定位函数Index_Sq(),若函数值为true,则得到串T在串S中的位置pos; ②调用删除子串函数StrDelete_Sq()从串S中pos开始删除串T; ③调用插入子串函数StrInsert_Sq()将串V插入到串S的第pos个字符之前。 重复上述过程,直至函数Index_Sq()的返回值为false终止。 其算法描述见算法4.10。 算法4.10 voidStrReplace_Sq(DSqString&S,DSqStringT,DSqStringV) { intpos; while(Index_Sq(S,T,pos)) { StrDelete_Sq(S,pos,T.length); StrInsert_Sq(S,pos,V); } }//StrReplace_Sq 11.串的遍历 voidStrTraveres_Sq(DSqStringS) { inti; for(i=0;i cout< cout< }//StrTraveres_Sq 12.撤销顺序串 voidDestroyString_Sq(DSqString&S) { free(S.str); S.str=NULL; S.length=0; }//DestroyString_Sq 4.C++中的串操作 #include"string" #include"iostream" usingnamespacestd; voidmain() { strings1="abcd",s2="123",s3; cout<<"串s1的值为: "< s1=s1+s2; cout<<"串s1和串S2连接后的值为: "< if(s1>s2)cout<<"s1>s2"< elseif(s1==s2)cout<<"s1=s2"< elsecout<<"s1 s1.insert(2,s2); cout<<"插入后的串s1为: "< s3=s1.substr(4,5); cout<<"子串s3为: "< } 4.3链式串及其操作 1.链式串的定义2.链式串的结构描述3.链式串的基本操作 1.链式串的定义 串的链式存储结构简称链式串。 链式串就是用链表来存储串值。 链表中每个结点可以存放一个字符,也可以存放多个字符,通常把结点大小为1链式串称为单链结构,结点中所存放的字符数称为结点大小。 通常把结点大小等于1的链式串称为单链结构,而把结点大小大于1的链式串称为块链结构。 如图4.1所示。 图4.1 2.链式串的结构描述 ⑴单链结构⑵块链结构 ⑴单链结构 在单链结构中一个结点存放一个字符,因此其结点结构与单链表一样,其结构描述如下: typedefstructLNode{ charstr; structLNode*next; }SNode,*SLinkString; 说明: 用单链结构表示串,其特点是处理灵活,但空间浪费较大,因为串中指针域占有较多的空间。 ⑵块链结构 用块链结构表示串,需要确定结点的大小,同时,为了便于进行串连接操作,除了头指针外,还增设一个尾指针,另外再增加一个成员以存放当前的串长。 其结构描述如下: #defineNumber80 typedefstructChunk{ charstr[Number]; structChunk*next; }Chunk; typedefstruct{ Chunk*head,*tail; intlength; }BLinkString; 说明: 用块链结构表示链式串,其特点是空间利用率高(指针域少),但处理不方便(在操作过程始终要注意结点的大小,超过其大小,才能进入到下一个结点)。 3.链式串的基本操作 1.串赋值2.串复制3.求串长4.串比较5.串连接6.取子串7.子串的定位8.插入子串 9.删除子串10.置换子串11.串的遍历12.撤销链式串 1.串赋值 串赋值操作就是把一个字符串常量赋值给链式串S。 其主要操作是: ①建立链式串S头结点; ②判断串常量chars是否为空串,若是,则串S置空,程序结束,否则执行③; ③重复为串S申请空间,用chars中的每一个字符建立一个单链表,直至chars结束。 其算法描述见算法4.13。 算法4.13 voidStrAssign_L(SLinkString&S,char*chars) { SLinkStringp,q; S=(SLinkString)malloc(sizeof(LNode)); if(! (*chars))S->next=NULL; else {p=S; while(*chars) {q=(SLinkString)malloc(sizeof(LN
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第4章