串的定义
串(string)是由零个或多个字符组成的有限序列,又名叫字符串。
一般记为 s = “ ”(n≥0),其中,s 是串的名称,用双引号括起来的字符序列是串的值。
串中的字符数目n称为串的长度。零个字符的串称为空串(null string)。它的长度为零,可以直接用两个双引号表示,也可以用希腊字母“φ‘’表示。
空格串:是只包含空格的串,空格串是有长度的,而且可以不止一个空格。
子串:串中任意个数的连续字符组成的子序列称为该串的子串。
主串:包含子串的串称为主串。
串的比较
事实上,串的比较是通过组成串的字符之间的编码来进行的,而字符的编码指的是字符在对应字符集中的序号。
在c语言中,判断两个串是否相等:必须是它们串的长度以及它们各个对应位置的字符都相等,才算是相等。
对于两个不相等的串,s = “”,t = “”,当满足以下条件之一时,s < t 。
1. n < m , 且 (i = 1,2,3, ......, n)。
例如,s = “lo”,t = “love”,就有s < t ,因为 t 比 s 多了两个字母。
2. 存在某个 k ≤ min(m,n),使得 (i = 1,2,3,......,k - 1),。
例如,当 s = “happen”,t = “happy”,因为两串的前4个字母相同,而第5个字母,字母 e 的 ASCII 码是101,而字母 y 的 ASCII 码是121,显然 e < y,所以 s< t 。
串的抽象数据类型
ADT 串 (String) Data 串中的元素仅由一个字符组成,相邻元素具有前驱和后继关系. Operation 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是非空串。 操作结果:用V替换主串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被销毁。 endADT
串的基本运算
对于串的基本操作,与线性表还是很有差别的,线性表关注的是单个元素的操作,比如查找一个元素,插入或是删除一个元素,但串中更多的是查找子串的位置、得到指定位置子串、替换子串等操作。
求串长:StrLength(s);
串赋值:StrAssign(s1,s2); // 将s2的串值赋予s1
连接运算:StrConcat(s1,s2,s) 或 StrConcat(s1,s2).//在s1后面连接s2的串值,产生新串s
求子串:SubStr(s,i,len);//返回s的第i至len个字符的子串值。len=0为空串。例如:SubStr("abcdefg",2,3) = "bcd"
串比较:StrComp(s1,s2);//若s1 =s2 ,操作返回值为0;s1<s2,返回值<0;反之>0
串定位:StrIndex(s,t);//若t被包含于s中,则返回值为t的位置,反之值为-1
串插入:StrInsert(s,i,t);//将串t插入到s的第i个字符位置上
串删除:StrDelete(s,i,len);//删除串t中第i至len个字符的子串
串修改:StrRep(s,t,r);//用串r替换s中出现的所有与串t相等且不重叠的子串
串的表示方法
串有3种机内的表示方法
1.定长顺序存储表示
类似于线性表中的顺序存储结构,是用一组地址连续的存储单元来存储串中的字符序列的。按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区。
串连接:把两个串s1和s2首尾连接成一个新串s,即s<-s1+s2
int StrConcat(s1,s2,s)
char s1[],s2[],s[];//将串s1,s2合并到串s,合并成功返回1,否则返回0
{
int i =0,j,len1,len2;
len1 = StrLength(s1);
len2 = StrLength(s2);
if(len1+len2>MAXSIZE-1) return 0; //s 长度不够
j = 0 ;
while(s1[j]! ="\0"){
s[i] = s1[j];
i++;
j++;
}
while(s2[j]! ="\0"){
s[i] = s2[j];
i++;
j++;
}
s[i] = "\0";
return 1;
}
求子串:
int StrSub(char *t ,char *s,int i , in len){
//用t返回串s中第i个字符串开始的长度为len的子串,1<=i串长
int slen;
slen = StrLength(s);
if(i<1 || i>slen || len<0 || len>slen-i+1){
return 0;
}
for(j =0 ; j<len ; j++){
t[j] =s[i+j-1];
t[j] ="\0";
return 1;
}
}
2.堆分配存储表示
在顺序串上的插入、删除操作并不方便,必须移动大量的字符,而且当操作中出现串值序列的长度超过上界MAXSIZE时,只能用截尾法处理。要克服这个弊病,只有不限定串的最大长度,动态分配串值的存储空间。
堆分配存储结构的特点是:仍以一组地址连续的存储单元存放串的字符序列,但其存储空间是在算法执行过程中动态分配得到的。在C语言中,由动态分配函数malloc()和free()来管理。利用函数malloc()为每一个新产生的串分配一块实际需要的存储空间,若分配成功,则返回一个指针,指向串的起始地址。
由于堆分配存储结构的串既有顺序存储结构的特点,在操作中又没有串长的限制,显得很灵活,因此,在串处理的应用程序中常被选用。
3.串的块链存储表示
串的链式存储与线性表相似,但由于串结构的特殊性,结构中的每个元素数据都是一个字符,如果也简单的应用链表存储串值,一个结点对应一个字符,就会存在很大的空间浪费,因此一个结点可以存放多个字符,最后一个结点若是未被占满时,可以用 "#" 或其它非串值字符补全。
为了便于进行串的操作,当以链表存储串值时,除头指针外还可附设一个尾指针指示链表中的最后一个结点,并给出当前串的长度。称如此定义的串存储结构为块链结构。