串(string),由字面意思理解就知道是和字符串有关的一种数据结构,它是由零个或者多个字符组成的有限序列,一般记为
s = ‘a1a2a3……an’(n>=0);
其中s为串名,用单引号括起来的字符序列是串的值,ai可以是字母,数字,或者是其他字符;
只有两个串的值相等才能称两个串是相等的,串值必须要用两个单引号括起来,但是单引号并不包含在串中,单引号的作用只是避免与变量名或者数的常量混淆。
由多个空格组成的串‘ ’称为 空格串,空串用Φ表示空串。
整体来看串的逻辑结构和线性表非常像,但是操作确实有很大的区别的,串的操作里,通常用串的整体作为操作对象。比如在串中查找一个子串,求取一个子串,在串的某个位置上插上一个子串,以及删除一个子串等。
int Index(SString S, SString T, int pos) { // 算法4.1
// T为非空串。若主串S中第pos个字符之后存在与T相等的子串,
// 则返回第一个这样的子串在S中的位置,否则返回0
int n,m,i;
SString sub;
if (pos > 0) {
n = StrLength(S);
m = StrLength(T);
i = pos;
while (i <= n-m+1) {
SubString (sub, S, i, m);
if (StrCompare(sub,T) == 0) ++i;
else return i;
} // while
} // if
return 0;
}
串的表示方法有三种:定长顺序存储表示,堆分配存储表示,块链式存储表示;
定长顺序存储表示,类似线性表的顺序存储结构,用一组地址连续的存储单元存储串值的字符序列;
#define MAXSTRLEN 255
typedef unsigned char SString[MAXSTRLEN+1];//0号单元存放串的长度
串的实际长度可以在预定义的长度里面任意定义,超出的部分的串值将被舍去,称为“截断”;
如果要将两个串连接,有三种情况:1,S[1]和S[2]的长度和都不超过MAXSTRLEN;2,S[1]和S[2]的长度和大于MAXSTRLEN但是S[1]的长度小于MAXSTRLEN;3,S[1]的长度大于MAXSTRLEN。那么在联结两个串的时候就要考虑这三种不同的情况。
Status Concat(SString &T, SString S1, SString S2) { //
// 用T返回由S1和S2联接而成的新串。若未截断,则返回TRUE,否则FALSE。
int i;
Status uncut;
if (S1[0]+S2[0] <= MAXSTRLEN) { // 未截断
for (i=1; i<=S1[0]; i++) T[i] = S1[i];
for (i=1; i<=S2[0]; i++) T[i+S1[0]] = S2[i];
T[0] = S1[0]+S2[0];
uncut = TRUE;
} else if (S1[0] < MAXSTRLEN) { // 截断
for (i=1; i<=S1[0]; i++) T[i] = S1[i];
for (i=S1[0]+1; i<=MAXSTRLEN; i++) T[i] = S2[i-S1[0]];
T[0] = MAXSTRLEN;
uncut = FALSE;
} else { // 截断(仅取S1)
for (i=0; i<=MAXSTRLEN; i++) T[i] = S1[i];
uncut = FALSE;
}
return uncut;
} // Concat
还有一个重要的操作就是求子串的操作:
Status SubString(SString &Sub, SString S, int pos, int len) {
// 用Sub返回串S的第pos个字符起长度为len的子串。
// 其中,1≤pos≤StrLength(S)且0≤len≤StrLength(S)-pos+1。
int i;
if (pos < 1 || pos > S[0] || len < 0 || len > S[0]-pos+1)
return ERROR;
for(i=1; i<=len; i++)
Sub[i] = S[pos+i-1];
Sub[0] = len;
return OK;
} // SubString
堆分配存储表示,这种存储表示的特点是,任然用一组连续的存储单元来存放串值字符序列,但是他们的存储空间是在程序执行的过程中动态分配来的。
//串的堆分配存储表示
typedef struct{
char *ch;//若是非空串,则按照串长分配存储区,否则ch为NULL
int length;//串长度
}Hstring;
(未完待续)