串,数组,广义表
一.串
【1】定义
1)是由零个或者多个字符组成的有限序列
2) 记作S=‘a1a2a3 an’
- 串名:s
- 串值:用单引号括起来的字符序列
- 长度:串中字符的数目
- 空串:含有零个字符的串
- 空格串:由一个或多个空串组合的串
- 子串:串中任意个连续的字符组合的子序列
- 字符在串的位置:子串的第一个字符在串中的位置
- 串相等:当且仅当两个串的值相等,即两个串的长度相等,且对应的字符相等
【2】关于定义的一个例子
1. 子串位置的查找
2.串的比较
给定两个串: X = ‘ x 1 x 2 … x n ’ X=‘x~1~x~2~…x~n~’ X=‘x 1 x 2 …x n ’和 Y = ‘ y 1 y 2 … y m ⋅ Y=‘y~1~y~2~…y~m· Y=‘y 1 y 2 …y m⋅’,则:
-
当 n = m n=m n=m且 x 1 = y 1 , … , x n = y m x~1~=y~1~,…,x~n~=y~m~ x 1 =y 1 ,…,x n =y m 时,称 X = Y X=Y X=Y;
-
当下列条件之一成立时,称X<Y:
⑴ $ n<m 且 且 且xi=yi(1≤ i ≤ n) $;⑵存在 k ≤ m i n ( m , n ) k ≤ min ( m,n ) k≤min(m,n),使得 x i = y i ( 1 ≤ i ≤ k − 1 ) x~i~=y~i~(1 ≤ i ≤k-1) x i =y i (1≤i≤k−1)且 x k < y k x~k~<y~k~ x k <y k 。
3.定位函数 Index (S, T, pos)
- 基本思想:从主串
S
S
S中取“第
i
i
i个字符起、长度和串
T
T
T相等的子串”和串
T
T
T比较,若相等,
则求得函数值为 i i i,否则 i i i值增 1 1 1直至找到相等的子串或者不存在和 T T T相等的子串为止。
int index(string s,string t,int pos)
{
//如果这个子串t不是空,那么查找pos后的有没有相等的子串
//如果有就开始返回第一个位置
if(t)
{
n=stingsize(s);
m=stringsize(t);
i=pos;
while(i<n-m+1)
{
substring(s,i,m);//将s从第i位取出m大小的子串
if(strcompare(sub,t)!=0)
i++;//如果不是0,那么向后移一位继续查找
else return i;//如果是0这次找到了,就返回子串的位置
}
}
}
【3】串的表示与实现
1.串的定长顺序存储表示
- 用一组地址连续的存储单元存储串值的字符序列
- 可用定长数组描述:
#define MAXSTRLEN 255;
typedef unsigned char SString[MAXSTRLEN +1];
2.两串相连
Status Concat(SString &T,SString S1,SString S2){
// 以T返回由S1和S2联接而成的新串,若未截断,返回TRUE,否则FALSE
if(S1[0]+S2[0]<=MAXSTRLEN){ //未截断
T[1..S1[0]]=S1[1..S1[0]];
T[S1[0]+1..S1[0]+S2[0]]=S2[1..S2[0]];
T[0]= S1[0]+S2[0];
uncut=TRUE;
}
else if (S1[0]<MAXSTRSIZE){ //截断
T[1..S1[0]]=S1[1..S1[0]];
T[S1[0]+1..MAXSTRLEN]=S2[1..MAXSTRLEN-S1[0]];
T[0]= MAXSTRLEN;
uncut=FALSE;
}
else { //截断 (仅取S1)
T[0.. MAXSTRLEN]=S1[0.. MAXSTRLEN];
uncut=FALSE;
}
return uncut;
} // Concat
3.求子串
Status SubString (SString &Sub,SString S,int pos,int len ){
//以Sub带回串S中第pos个字符起长度为len的子串
//其中,1≤pos≤StrLength(S) 且0≤len≤StrLength(S)-pos+1
if ( pos<1 || pos>s[0] || len<0 || len > s[0]-pos+1)
return ERROR;
Sub[1..len] = S[pos..pos+len-1];
Sub[0] = len;
return OK;
} // SubString
【4】串三种储存
1.串的顺序储存
typedef struct {
char ch[MAX];
int length; // 串长度
} HString;
2.串的堆式储存
typedef struct {
char *ch;
int length; // 串长度
} HString;
status strassign(hstring &t,char *chars) {
//生成一个其值等于串常量chars的串t
if(t.ch) free(t.ch);
for(i=0,c=chars; c ;++i,++c);
if(!i) { t.ch=NULL; t.length=0; }
else{
if(!(t.ch=(char *)malloc(I*sizeof(char)))) exit(overflow);
t.ch[0..i-1]=chars[0..i-1];
t.length=i; }
return OK; }
3.串的块链存储表示
【1】可采用链表方式存储串值,每个结点可以存放一个字符,也可以存放
多个字符 (如图所示)。
//串的块状储存
#define CHUNKSIZE 80//可由用户定义的块大小
typedef struct chunk{
char ch[CHUNKSIZE];
struct chunk *next;
}chunk;
typedef struct{
chunk *head,*tail;//串的头尾
int cuirlen;//串的长度
}
【2】储存密度
存储密度=串值所占的存储位/实际分配的存储位。
【5】串的N中应用
1. 模式匹配Index()
详见上述
2.BF算法
1)基本思想:
A. 从主串 s s s中的第一个字符开始和模式 T T T的第一个字符进行比较,
- 若相等,则继续比较两者的后序字符
- 若不相等,则从主串的第二个字符开始与模式T的第一个字符进行比较
B.重复上述过程
-
若 T T T中的字符全部比较完毕,则说明本躺匹配成功
-
S S S中的字符全部比较完,说明匹配失败
2)缺点 :
A. 算法的一次执行时间不容忽视:问题规模通常很大,常常需要在大量信息中进行匹配;
B. 算法改进所取得的积累效益不容忽视:模式匹配操作经常被调用,执行频率高。
3)算法过程:
4)算法:
//BF算法
void BP(sstring &t,sstring s,int pos)
{ i=pos;j=1;//i表示为在s中开始的地方(如果没有要求就为1)
//j表示子串T开始的地方
while(i<s[0]&&j<=t[0])
{
if(s[i]==t[j])
{
i++;j++;
}
else {i=i-j+2;j=1;}
}
if(j>t[0]) return i-t[0];//成功
else return 0;
}
5)复杂度:
A. 最坏情况:不成功匹配都发生在串T的最后一个字符。
B.最好情况:不成功匹配都发生在串T的第1个字符
3.KMP算法
void get_next() {
next[0] = -1;
int i = 0, j = -1;
int len = strlen(T);
while(i < len) {
if(j == -1 || T[i] == T[j])
next[++i] = ++j;
else
j = next[j];
}
}
bool KMP() {
get_next();
int len1 = strlen(T);
int len2 = strlen(S);
int i = 0, j = 0; //i指向模式串T,j指向主串S
while(j < len2) {
if(T[i] == S[j]) {
i++;
j++;
if(i == len1) {
return true;
}
} else {
i = next[i];
if(i == -1) {
j++;i++;
}
}
}
return false;
}