串的定义
串(string)(或字符串)是由零个或多个字符组成的有限序列,一般记为,
s=“a1,a2…an”(n≥0)
- n为字符串的
长度
- 零个字符的串称为
空串
,其长度也为0 - 串中任意个连续的字符组成的子序列称为该串的
子串
- 包含字串的串称为
主串
- 通常称字符在序列中的序号为该字符在串中的
位置
子串在主串中的位置
则以子串的第一个字符在主串中的位置来表示- 只有两个串的长度相等,并且各个对应位置的字符都相等才称为两个串是
相等
的 - 由一个或多个空格组成的串称为
空格串
(不是空串)
串的抽象类型定义
串的抽象数据类型定义如下:
ADT String{
数据对象:D={ ai | ai ∈ CharacterSet,i=1,2,…,n,n≥0}
数据关系:R1={ < a(i-1),ai > | a(i-1),ai ∈ D,i=2,…,n }
基本操作:
StrAssign(&T,chars) 生成一个其值等于chars的串T(chars是字符串常量)
StrCopy(&T,S) 由串S复制得T
StrEmpty(S) 若S为空串,返回true,否则返回false
StrCompare(S,T) 若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
StrLength(S) 返回S的元素个数,称为串的长度
ClearString(&S) 将S清为空串
Concat(&T,S1,S2) 用T返回由S1和S2联接而成的新串
SubString(&Sub,S,pos,len) 用Sub返回串S的第pos个字符起长度为len的子串
Index(S,T,pos) 若主串S中存在和串T值相同的子串,则返回它在主串S中第pos个字符之后第一次出现的位置;否则函数值为0
Replace(&S,T,V) 用V替换主串S中出现的所有与T相等的不重叠的子串
StrInsert(&S,pos,T) 在串S的第pos个字符之前插入串T
StrDelete(&S,pos,len) 从串S中删除第pos个字符起长度为len的子串
DestroyString(&S) 销毁串S
串的顺序存储
类似于线性表的顺序存储结构,用一组地址连续的存储单元存储串值的字符序列。按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区,则可用定义数组如下描述:
//串的定长顺序存储结构
#define MAXLEN 255 //串的最大长度
typedef struct{
char ch[MAXLEN+1]; //存储串的一维数组
int length; //串的当前长度
}SString;
为了便于说明问题,本章后面算法描述当中所用到的顺序存储的字符串都是从下标为1的数组分量开始存储的,下标为0的分量闲置不用。这种定义方式是静态
的,在编译时刻就确定了串空间的大小。
在c语言中,存在一个称之为“堆”(Heap)的自由存储区,可以为每个新产生的串动态
分配一块实际串长所需的存储空间,若分配成功,则返回一个指向起始地址的指针,作为串的基址,同时为了以后处理方便,约定串长也作为存储结构的一部分。这种字符串的存储方式也称为串的堆式顺序存储结构,定义如下:
//串的堆式顺序存储结构
typedef struct{
char *ch; //若是非空串,则按串长分配存储区,否则ch为NULL
int length; //串的当前长度
}HString;
串的链式存储
顺序串的插入和删除操作不方便,需要移动大量的字符。因此,可采用单链表方式存储串。每个结点可以存放一个字符,也可以存放多个字符。
为了便于进行串的操作,当以链表存储串值时,除头指针外,还可附设一个尾指针指示链表中的最后一个结点,并给出当前串的长度。称如此定义的串存储结构为块链结构,说明如下:
//串的链式存储结构
#define CHUNKSIZE 80 //可由用户定义的块大小
typedef struct Chunk{
char ch[CHUNKSIZE];
struct Chunk*next;
}Chunk;
typedef struct{
Chunk *head,*tail; //串的头和尾指针
int length; //串的当前长度
}LString;
借鉴:《数据结构》 严蔚敏