一. 串类型的定义
字符串是n(n>=0)个字符的有限序列,记作:
S=“C1C2C3...Cn”
其中:
- S是串名字;
- “C1C2C3…Cn” 是串值;
- Ci 是串中字符;
- n 是串的长度;
- n=0 称为空串;
- 由一个或多个空白符组成的串称为空白串;
- 串中任意个连续字符组成的子序列称为该串的子串;
- 包含子串的串相应地称为主串;
- 通常将子串在主串中首次出现时,该子串首字符对应的主串中的序号,定义为子串在主串中的位置。
例如,设 A = “This is a string” , B = “is” 则B是A的子串,A为主串。B在A中出现了两次,首次出现所对应的主串的位置是2(从0开始)。因此,称B在A中的位置为2.
- 空串是任意串的子串,任意串是其自身的子串。
二. 串的表示和实现
除C语言提供的字符串库函数外,可以自定义字符串。
适用于自定义字符串数据类型的有三种存储表示:
定长顺序存储表示
;堆分配存储表示
;块链存储表示
。
定长顺序存储表示
- 顺序串:使用静态分配的字符数组存储字符串中的字符序列。
- 字符数组的长度预先用MAXSTRLEN确定,一旦空间存满,不能扩充。
- 有两种实现定长顺序存储表示:
- 字符串存放于字符数组的0 ~ MAXSTRLEN-1单元,另外用整数length记录串中实际存放的字符个数。
- 字符串存放于字符数组的1 ~ MAXSTRLEN-1单元,用0号单元记录串中实际存放的字符个数。
- 定长存储表示的定义如下:
#define MAXSTRLEN 256 //顺序串的预设长度
typedef struct{ //顺序串的定义
char SString[MAXSTRLEN] //存储字符数组
int length; //串中实际字符个数
}SqString;
堆分配存储表示
- 堆式串:字符数组的存储空间是通过malloc()函数动态分配的。
- 串的最大空间数MAXSTRLEN和串中实际字符个数length保存在串的定义中。
- 可以根据需要,随时改变字符数组的大小。
- 堆分配存储表示的定义如下:
#define MAXSTRLEN 256 //顺序串的预设长度
typedef struct{
char *ch; //存储字符数组
int maxSize; //串数组的最大长度
int length; //串的当前长度
}HString;
块链存储表示
- 使用单链表作为字符串的存储表示,此即字符串的链接存储表示。
- 链表的每个结点可以存储1个字符,称其块的大小为1,也可以存储n个字符,称其块的大小为n。
- 定义存储密度为:
存储密度越高,存储利用率越高。
块链存储表示一般带头结点,设置头,尾指针。
- 块链存储表示的定义如下:
#define blockSize 4 //由使用者定义的结点大小
typedef struct bloak{ //
char ch[blockSize];
struct block *next;
}Chunk;
typedef struct{
Chunk *first, *last; //链表的头指针和尾指针
int length; //串的当前长度
}LString;
存储利用率分析
结点大小为4时,存储利用率高,但操作复杂,需要析出单个字符。
结点大小为1时,存储利用率低,但操作简单,可直接存取字符。
三. 串的相关算法(堆存储部分操作的实现)
初始化空串算法
void initString(Hstring &S)
{
S.ch = (char *)malloc(MAXSTRLEN*sizeof(char)); //分配字符数组空间
if(S.ch == NULL)
exit(1); //判断分配是否成功
S.ch[0] = '\0'; //置空串
S.maxSize = MAXSTRLEN; //置串的最大字符数
S.length = 0; //实际字符数置0
}
提取子串算法
代码实现:
HString subString(HString &s, int pos, int len)
{
HString tmp;
//创建子串空间
tmp.ch = (char *)malloc(MAXSTRLEN*sizeof(char));
tmp.maxSize = MAXSTRLEN;
if(pos<0 || len<0 || pos+len-1 >= s.maxSize)
{ //参数不合理,返回空串
tmp.length = 0;
tmp.ch[0] = '\0';
}
else
{
if(pos+len-1 >= s.length)
len = s.length-pos;
for(int i=0, j=pos; i<len; i++, j++)
tmp.ch[i] = s.ch[i]; //复制子串的字符
tmp.length = len;
tmp.ch[len] = '\0';
}
return tmp; //返回复制的子串
}
串的连接算法
void concat(HeapString &s, Heapstring &t)
{
if(s.length + t.length <= s.maxSize)
{ //原空间可容纳连接后的串
for(int i=0; i<t.n; i++)
s.ch[s.length+i] = t.ch[i]; //串t复制到串s后
s.length = s.length + t.length;
s.ch[s.length]= '\0';
}
else //原空间容不下连接后的串
{
char *tmp = s.ch;
s.maxSize = s.length + t.length;
s.ch = (char *)malloc((s.maxSize+1)*sizeof(char));
strcpy(s.ch, tmp); //复制原串s数组
strcat(s.ch, t.ch); //连接串t数组
s.length = s.length + t.length;
free(tmp);
}
}