数据结构
-
Upload
hayfa-david -
Category
Documents
-
view
34 -
download
0
description
Transcript of 数据结构
4.1 串类型的定义一、串定义:串是由多个或零个字符组成的有限序列 ,记作:S = ‘c1c2c3…cn’ (n>=0) 其中, S 是串名
字,‘ c1c2c3…cn’ 是串值, ci是串中字符, n 是串的长度,表示串中字符
的数目。空串:零个字符的串称为空串 记作 “ Ø”子串:串中任意个连续的字符组成的子序列主串:包含子串的串字符在串中的位置:字符在序列中的序号子串在串中的位置:子串的第一个字符在主串中的位置串相等: p70空格串:由一个或多个空格组成的串串的表示:用一对单引号括起来
1.定长顺序存储表示
静态分配每个串预先分配一个固定长度的存储区域。实际串长可在所分配的固定长度区域内变动,以下标
为 0 的数组分量存放串的实际长度;在串值后加入” \0”表示结束,此时串长为隐含值。
用定长数组描述:#define MAXSTRLEN 255 //最大串长typedef unsigned char SString[MAXSTRLEN + 1]
//0号单元存放串的长度
4.2 串的表示和实现
2.堆分配存储表示
以一组地址连续的存储单元存放串值字符序列;存储空间动态分配,用 malloc()和 free()来管理。
typedef struct { char *ch; // 若是非空串,则按串实用长度分配 //存储区,否则 ch 为 NULL int length; // 串长度 } HString;
4.串的基本操作串插入 Status StrInsert(HString &S,int pos,HString T)
串赋值 Status StrAssign(HString &S,char *chars)求串长 int StrLength(HString S)串比较 int StrCompare(HString S,HString T)串联接 Status Concat(HString &S,HString S1,HString S2)
求子串 Status SubString(HString &Sub,HString S,int pos,int len)
串清空 Status ClearString(HString &S)串定位删除置换
Status StrInsert(HString &S,int pos,HString T)//在串 S 的第 pos个位置前插入串 S{ int i;if (pos<1||pos>S.length+1) return ERROR;if (T.length){
if (!(S.ch=(char*) realloc(S.ch,(S.length+T.length)*sizeof(char))))
exit(OVERFLOW);for (i=S.length-1;i>=pos-1;--i){
S.ch[i+T.length]=S.ch[i];}for (i=0; i<=T.length-1;i++)
S.ch[pos-1+i]=T.ch[i];S.length+=T.length;
} return OK;}
Status StrAssign(HString &S,char *chars)生成一个值等于 chars的串 S
{ int i,j; char *c;for (i=0,c=chars;*c;++i,++c);if (!i) {S.ch=NULL; S.length=0;}else {
if (!(S.ch=(char *)malloc(i * sizeof(char))))
exit(OVERFLOW);for (j=0;j<=i-1;j++){
S.ch[j]=chars[j];}S.length=i;
}return OK;
}
int StrLength(HString S)求串的长度{return S.length;
}
int StrCompare(HString S,HString T)比较两个串,若相等返回 0{int i;for (i=0;i<S.length && i<T.length; ++i)
if (S.ch[i] != T.ch[i]) return S.ch[i]-T.ch[i];
return S.length-T.length;}
Status Concat(HString &S,HString S1,HString S2)用 S 返回由 S1和 S2联接而成的新串{ int j;if (!(S.ch = (char*)malloc((S1.length+S2.length)*sizeof(char))))
exit(OVERFLOW);for (j=0;j<=S1.length-1;j++){
S.ch[j]=S1.ch[j];}S.length=S1.length+S2.length;for (j=0;j<=S2.length-1;j++){
S.ch[S1.length+j]=S2.ch[j];}return OK;
}
Status SubString(HString &Sub,HString S,int pos,int len)用 Sub返回串 S 的第 pos个字符开始长度为 len的子串{
if (pos<1 || pos>S.length || len<0 ||len>S.length-pos+1)
return ERROR;if (!len) { Sub.ch=NULL; Sub.length=0;}else {
Sub.ch=(char *)malloc(len*sizeof(char));
for (int j=0;j<=len-1;j++){Sub.ch[j]=S.ch[pos-1+j];}
Sub.length=len;}return OK;
}
4.3 串的模式匹配算法
定义 在串中寻找子串(第一个字符)在串中的位置词汇 在模式匹配中,子串称为模式,串称为目标。示例 目标 S : “Beijing”
模式 P : “jin”
匹配结果 = 4 1.穷举模式匹配 设 S=s1,s2,…,sn(主串 )P=p1,p2,…,pm(模式串 ),i为
指向 S 中字符的指针, j 为指向 P 中字符的指针匹配失败:si≠pj 时,(si-j+1 … si-1)=(p1 … pj-1)
回溯: i=i-j+2 ; j=1重复回溯太多, O(m*n)
第 1 趟 S a b b a b a 穷举的模式 P a b a 匹配过程
第 2 趟 S a b b a b a P a b a
第 3 趟 S a b b a b a
P a b a
第 4 趟 S a b b a b a P a b a
求子串位置的定位函数
int Index(SString S, SString T,int pos) {//穷举的模式匹配int i=pos; int j=1;while (i<=S[0] && j<=T[0]) {//当两串未检测完,S[0]、 S[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;
}
S s1… si-j-1 si-j si-j+1 si-j+2 … si--1 si si+1 …sn
‖ ‖ ‖ ‖ P p1 p2 … pj--1 pj pj+1
…… p pmm
则有 si-j+1 si-j+2 … si-1 = p1 p2 …pj-1 (1) 为使模式 P 与目标 S 匹配,必须满足 p1p2 …pj-1pj …pm = si-j+1si-j+2…si-1 si…si-j+m
如果 p1 …pj-2 p2 p3 …pj-1 (2) 由 (1)(2)则立刻可以断定 p1 …pj-2 si-j+2 si-j+3 … si-1
下一趟必不匹配
同样,若 p1 p2 …pj-3 p3 p4 …pj-1则再下一趟也不匹配,因为有
p1 …pj-3 si-j+3 … si-1直到对于某一个“ k”值,使得 p1 …pk pj-k pi-k+1 …pj-1且 p1 …pk-1 = pj-k+1 pj-k+2 …pj-1则
p1 …pk-1 = si-k+1 si-k+2 … si-1 ‖ ‖ ‖ pj-k+1 pj-k+3 … pj-1模式右滑 j-k位
next数组值
假设当模式中第 j 个字符与主串中相应字符“失配”时,可以拿第 k 个字符来继续比较,则令 next[j]=k
next函数定义: 0 当 j=1时next[j]= Max{k| 1<k<j 且’ p1…pk-1’=‘pj-k+1…pj-1’}
当此集合不空时 1 其他情况
手工求 next数组的方法 :
序号 j 1 2 3 4 5 6 7 8模式 P a b a a b c a c k 1 1 2 2 3 1 2Pk==Pj ≠ = ≠ = ≠ = ≠next[j] 0 1 1 2 2 3 1 2 Nextval[j] 0 1 0 2 1 3 0 2
运用 KMP算法的匹配过程
第 1 趟 目标 a c a b a a b a a b c a c a a b c 模式 a b a a b c a c next(2) = 1第 2 趟 目标 a c a b a a b a a b c a c a a b c
模式 a b a a b c a c next(1)=0第 3 趟 目标 a c a b a a b a a b c a c a a b c
模式 a b a a b c a c next(6)
= 3 第 4 趟 目标 a c a b a a b a a b c a c a a b c 模式 (a b)a a b c a c
KMP算法int Index_KMP(SString S, SString T, int *next){ int i,j;i=1; j=1;while (i<=S[0] && j<=T[0]){
if (j==0 || S[i]==T[j]){++i;++j;}else j=next[j];
}if (j>T[0]) return i-T[0];else return 0;
}
求 next数组的步骤
(1)next[1]=0 i=1; j=0; (2)设 next[i]=j若 j=0, next[i+1]=1若 Pi=Pj, next[i+1]=j+1=next[i]+1若 Pi ≠ Pj, next[i+1]=next[j]+1参看教材 p82~83递推过程
求 next数组的函数void get_next(SString S, int *next){int i,j;i=1;next[1]=0; j=0;while (i<S[0]) {
if (j==0 || S[i]==S[j]) {++i; ++j; next[i]=j;}
else j=next[j];}
}
改进的求 next数组的函数void get_nextval(SString S, int *nextval){int i,j;i=1; nextval[1]=0; j=0;while (i<S[0]) {
if (j==0 ||S[i]==S[j]){++i;++j;if (S[i]!=S[j]) nextval[i]=j;else nextval[i]=nextval[j];
}else j=nextval[j];
}}