串类型的定义
串是由零个或多个字符组成的有限序列。
串中字符的数目n称为串的长度。零个字符的串称为空串。
串中任意个连续的字符组成的子序列称为该串的子串。
包含子串的串相应地称为主串。通常称字符在序列中的序号为该字符在串中的位置。
串值必须用一对单引号括起来。单引号本身不属于串,它的作用只是为了避免与变量名或数的常量混淆而已。
例如 x=’123’; x是一个串变量名,字符序列123是其值。
由一个或多个空格组成的串’’称为空格串(注意不是空串)。
串的逻辑结构和线性表极为相似,区别仅在于串的数据对象约束为字符集。
串的基本操作和线性表有很大差别。
串的基本操作中,通常以“串的整体”作为操作对象。
串的表示和实现
在多数非数值处理的程序中,串也以变量的形式出现。串有3种机内表示方法。
存储结构不同,操作也就不同;
定长顺序存储表示
类似于线性表的顺序存储结构,用一组地址连续的存储单元存储串值的字符序列。
在串的定长顺序存储结构中,按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区。
串的实际长度可在这预定义长度的范围内随意,超过预定义长度的串值则被舍去,称之为“截断”。(预定义串最大长度有个弊病,就是在进行串联接时可能产生截断的情况。克服该问题的方法就是动态分配串值的存储空间。)
以下标为0的数组分量存放串的实际长度。
在串后面加上一个不计入串长的结束标记字符:C语言中以“ ”表示串值的终结。串长为隐含值。
在这种存储结构中如何实现串的操作:1)串联接,2)求子串
顺序存储结构中,串操作的原操作为“字符序列的复制”。
操作的时间复杂度取决于字符序列的长度。
另一个操作特点:如果在操作中出现串值序列的长度超过上界,约定用截尾法处理。这种弊病在求联接串时可能发生,在串的其他操作中,如插入,置换等也可能发生。克服这种弊病的方法就是不限定串长的最大长度。
堆分配存储表示
在C语言中,存在一个称之为“堆”的自由存储区。并由C语言动态分配函数malloc()和free()来管理。利用函数malloc()为每个新产生的串分配一块实际串长所需的存储空间。
堆是内存中的一块特定存储区域,用于在程序运行过程中动态分配存储空间。
若分配成功,则返回一个指向起始地址的指针,做为串的基址。
同时为了以后处理方便,约定串长也作为存储结构的一部分。
串的堆分配存储表示
typedef struct
{
char *ch;
int length;
}HString;
这种存储结构表示时的串操作仍是基于“字符序列的复制”进行的。
串复制操作StrCopy(&T,S):若串T已存在,则先释放串T所占空间,当S不空时,首先为串T分配大小和串S长度相等的存储空间。然后将串S的值复制到串T中。
串插入操作StrInsert(&S, pos, T):将串S重新分配大小等于串S和串T长度之和的存储空间,然后进行串值复制。
堆分配存储结构的串既有顺序存储结构的特点,处理方便。操作中对串长又没有任何限制,更显灵活。
串的块链存储表示
当以链表存储串值时,除头指针外还可以附设一个尾指针指示链表中的最后一个结点,并给出当前串的长度。设尾指针的目的是为了便于进行联结操作,但应注意联结时需处理第一个串尾的无效字符。如此定义的串存储结构称为块链结构。块的大小根据需要选择。块太大的化,处理不灵活。块太小则存储密度小。总体来说这种存储结构不如前两种灵活方便。占用存储空间大而且操作复杂。只有在联结操作时有一定方便之处。