目录
串的定义
串是一种特殊的线性表,串或者字符串是由一个或者多个字符组成的有限序列。一般记为:S="a1a2......an" (n>=0)
其中S是串名,n为串的长度,n=0时其为空串。双引号中的元素可以为数字、字母或者字符。
串中任意个连续的字符组成的子序列称为该串的子串,包含子串的串相应地称为主串。通常称字符在序列中的序号为该字符在串中的位置。子串在 主串中的位置则以子串的第一个字符在主串中的位置来表示。下面举一些例子进一步理解:
例:设A、B、C、D四个串:
A="abc123" ,B="123"
C="abc",D="abc 123"。
对于以上四个字符串,B和C时A的子集也是D的子集,但A和D不能等同而且A不是D的子集D也非A的子集。因为D中有空格。(由一个或者多个空格组成的串称为空格串,它的长度取决于空格的个数)注:空串不等于空格串。
对于B和C在主串上的位置,则B在A的第一位,C在A的第四位。B在D的第一位,C在D的第五位。
串的存储结构
由于串也是一种特殊的线性表,所以也应该由两种存储结构,即串的顺序存储和链式存储。首先要先了解串的一些基本操作。
串的抽象类型定义
串的基本操作:
ADT String
{
数据对象: D={ailai∈CharacterSet,i=1,2,n,n≥0}
数据关系:R1=(<ai-1,ai> lai-1,aieD,12-.n)
基本操作:
StrAssign (&T, chars)
初始条件: chars是字符串常量。
操作结果:生成一个其值等于chars的串T。
StrCopy(&T,S)
初始条件:串s存在。
操作结果:由串s复制得串T。
StrEmpty (S)
初始条件:串s存在。
操作结果:若s为空串,则返回true,否则返回false。
StrCompare(S,T)
初始条件:串s和T存在。
操作结果:若S>T,则返回值>0 ;若s=T,则返回值=0;若S<T,则返回值<0。
StrLength(S)
初始条件:串s存在。
操作结果:返回S的元素个数,称为串的长度。
ClearString (&S)
初始条件:串s存在。
操作结果:将s清为空串。
Concat (&T,S1,S2)
初始条件:串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是非空串。
操作结果:用Vv替换主串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的子串。
DestroyString (&S)
初始条件:串s存在。
操作结果:串s被销毁。
}ADT String
串的顺序存储
//串的顺序存储结构(静态分配内存空间)
#define MAXLEN255//串的最大长度
typedef struct
{
charch [MAXLEN+1] ;//存储串的一维数组
intlength; //串的当前长度
} SString;
上边的是利用静态数组实现的定长顺序存储,在编译之前就确定了大小会导致空间的不尽合理。因此下面用动态数组实现的堆分配存储:
typedef struct
{
char *ch;
int length;
}HString;
HString S;
S.ch=(char *)malloc(MAXLEN*sizeof(char));
S.length=0;
顺序串的插入删除操作不方便,需要移动大量的字符。
串的链式存储
//串的链式存储结构
#define CHUNKSIZE80 //可由用户定义的块大小
typedef struct Chunk
{
char ch[ CHUNKSIZE ;
struct Chunk *next;
}Chunk;
typedef struct
{
Chunk *head, *tail; //串的头和尾指针
int length; //串的当前长度
} LString;
对于串的存储,一般采用顺序存储结构,链式存储的存储密度较低,导致存储占用量大,而且节点的大小的选择影响着串处理的效率,没有顺序存储结构灵活。
串的模式匹配算法
BF算法
该算法也称为简单匹配算法,是采用穷举法的思路。
其算法步骤如下:
1.分别利用计数指针 i 和 j 指示主串S和模式 T 中当前正待比较的字符位置,i的初始值为pos, j的初始值为1。
2.如果两个串均未比较到串尾,即 i 和 j 均分别小于等于S和T的长度时,则循环执行以下操作:
1>S.ch[j和T.ch[j比较,若相等,则和j分别指示串中下个位置,继续比较后续字符;
2>若不相等,指针后退重新开始匹配,从主串的下一一个字符(i=ij+2)起再重新和模式的第一一个字符(j=1)比较。
3.如果 j > T.length,说明模式T中的每个字符依次和主串S$中的一一个连续的字符序列相等,则匹配成功,返回和模式中第一个字符相等的字符在主串S中的序号(i-T.lengh);否则称匹配不成功,返回0。
其代码如下:
int Index BF (SStrings,sstring T,int pos)
{//返回模式中在 主中S中第pos个字符开始第一次出现的位置。若不存在,则返回0
//其中,T非空,1≤pos≤s.length
i=pos; j=1 ;//初始化
while(i≤s.1ength && j≤T. length)//两个串均未比较到串尾
if(s.ch[i]==T.ch[j]) {++i;++j;}
//继续比较后继字符
else{i=i-j+2;j=l; }//指针后退,重新开始匹配
if(j> T. length) return i-T.length; //匹配成功
else return 0; //匹配失败
}
算法图解:
第一趟匹配,pos=1,即i从1与j=1开始匹配,当i=3时匹配失败,则进行第二趟匹配即pos+1=2,i从2与j=1开始匹配,i=2时匹配失败,则以此类推匹配,直到匹配成功为止。