第4章 串Word文档格式.docx
《第4章 串Word文档格式.docx》由会员分享,可在线阅读,更多相关《第4章 串Word文档格式.docx(32页珍藏版)》请在冰豆网上搜索。
s1>
s2,s3<
s4
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的元素个数,即串的长度。
StrCompare(S,T)
串S和T存在。
若S<
T,则返回值<
0;
若S=T,则返回值=0;
若S>
T,则返回值>
0。
StrConcat(&
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被撤销。
}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;
//存放非空串的首地址
//存放串的当前长度
}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++);
i){S.str=NULL;
S.length=0;
}
else{
if(!
(S.str=(char*)malloc(i*sizeof(char))))
returnfalse;
for(j=0;
j<
i;
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;
T.length){S.str=NULL;
(S.str=(char*)malloc(T.length*sizeof(char))))
returnfalse;
for(i=0;
i<
T.length;
i++)
S.str[i]=T.str[i];
S.length=T.length;
}//StrCopy_Sq
3.求串长
intStrLength_Sq(DSqStringS)
{
return(S.length);
}//StrLength_Sq
4.串比较
比较顺序串S和顺序串T,若S<
T,则返回值小于0;
若S=T,则返回值等于0;
T,则返回值大于0。
从顺序串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<
S.length&
&
T.length)
{
if(S.str[i]>
T.str[i])return1;
elseif(S.str[i]<
T.str[i])return-1;
i++;
if(i<
S.length)return1;
elseif(i<
T.length)return-1;
return0;
}//StrCompare_Sq
5.串连接
将顺序串T连接在顺序串S之后,并返回连接后的顺序串S。
①判断顺序串T的长度是否为非0,若是,则为顺序串S增补T.length个数据元素的空间;
②把顺序串T中的所有字符复制到顺序串S中去,同时将顺序串S的长度增加T.length。
其算法描述见算法4.5。
算法4.5
boolStrConcat_Sq(DSqString&
if(T.length){
(S.str=(char*)realloc(S.str,(S.length+T.length)*sizeof(char))))
S.str[S.length+i]=T.str[i];
S.length+=T.length;
}//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)
if(pos<
0||pos>
S.length-1||len<
0||len>
S.length-pos)
if(Sub.str)free(Sub.str);
len){Sub.str=NULL;
Sub.length=0;
(Sub.str=(char*)malloc(len*sizeof(char))))
for(i=0;
len;
Sub.str[i]=S.str[pos+i];
Sub.length=len;
}//SubString_Sq取子串操作过程演示
7.子串的定位
子串的定位操作也叫串查找操作、串的模式匹配操作。
它是在主串S中查找是否存在和串T值相同的子串,若存在,则匹配成功,并由pos返回它的第一个字符在主串S中第一次出现的位置,否则匹配失败。
将串S的第一个字符和串T的第一个字符进行比较,若相等,则继续比较两者的后续字符;
否则,将串S的第二个字符和串T的第一个字符进行比较,重复上述过程,若串T中的字符全部比较完毕,则本趟匹配成功,函数返回true;
其算法描述见算法4.7。
算法4.7
boolIndex_Sq(DSqStringS,DSqStringT,int&
inti=0,j=0;
{if(S.str[i]==T.str[j])
{i++;
j++;
else
{i=i-j+1;
j=0;
if(j==T.length){pos=i-T.length;
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)
S.length)returnfalse;
if(T.str)
for(i=S.length-1;
i>
=pos;
i--)
S.str[i+T.length]=S.str[i];
S.str[pos+i]=T.str[i];
S.length=S.length+T.length;
}//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)
0||len<
0||pos+len>
for(i=pos+len;
=S.length-1;
S.str[i-len]=S.str[i];
S.str=(char*)realloc(S.str,(S.length-len)*sizeof(char));
S.length=S.length-len;
}//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)
StrLength_Sq(S);
i++)
cout<
<
S.str[i];
endl;
}//StrTraveres_Sq
12.撤销顺序串
voidDestroyString_Sq(DSqString&
free(S.str);
S.str=NULL;
}//DestroyString_Sq
4.C++中的串操作
#include"
string"
iostream"
usingnamespacestd;
voidmain()
strings1="
abcd"
s2="
123"
s3;
"
串s1的值为:
s1<
s1=s1+s2;
串s1和串S2连接后的值为:
if(s1>
s2)cout<
s2"
elseif(s1==s2)cout<
s1=s2"
elsecout<
s1.insert(2,s2);
插入后的串s1为:
s3=s1.substr(4,5);
子串s3为:
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;
}BLinkString;
用块链结构表示链式串,其特点是空间利用率高(指针域少),但处理不方便(在操作过程始终要注意结点的大小,超过其大小,才能进入到下一个结点)。
3.链式串的基本操作
1.串赋值2.串复制3.求串长4.串比较5.串连接6.取子串7.子串的定位8.插入子串
9.删除子串10.置换子串11.串的遍历12.撤销链式串
串赋值操作就是把一个字符串常量赋值给链式串S。
①建立链式串S头结点;
②判断串常量chars是否为空串,若是,则串S置空,程序结束,否则执行③;
③重复为串S申请空间,用chars中的每一个字符建立一个单链表,直至chars结束。
其算法描述见算法4.13。
算法4.13
voidStrAssign_L(SLinkString&
SLinkStringp,q;
S=(SLinkString)malloc(sizeof(LNode));
(*chars))S->
next=NULL;
else
{p=S;
while(*chars)
{q=(SLinkString)malloc(sizeof(LN