一、考试内容:
1,串的存储结构及基本运算的实现;
串中元素逻辑关系与线性表的相同,串可以采用与线性表相同的存储结构。
#define MaxSize 100
typedef struct
{ char data[MaxSize]; //存储字符串
int length; //存储长度
} SqString;
串抽象数据类型=逻辑结构+基本运算(运算描述)
串的基本运算如下:
StrAssign(&s,cstr):将字符串常量cstr赋给串s,即生成其值等于cstr的串s。
StrCopy(&s,t):串复制。将串t赋给串s。
StrEqual(s,t):判串相等。若两个串s与t相等则返回真;否则返回假。
StrLength(s):求串长。返回串s中字符个数。
Concat(s,t):串连接:返回由两个串s和t连接在一起形成的新串。
SubStr(s,i,j):求子串。返回串s中从第i(1≤i≤n)个字符开始的、由连续j个字符组成的子串。
InsStr(s1,i,s2):插入。将串s2插入到串s1的第i(1≤i≤n+1)个字符中,即将s2的第一个字符作为s1的第i个字符,并返回产生的新串。
DelStr(s,i,j):删除。从串s中删去从第i(1≤i≤n)个字符开始的长度为j的子串,并返回产生的新串。
RepStr(s,i,j,t):替换。在串s中,将第i(1≤i≤n)个字符开始的j个字符构成的子串用串t替换,并返回产生的新串。
DispStr(s):串输出。输出串s的所有元素值。
串的顺序存储/定长存储结构
两种方法:1,每个单元(如4个字节)只存一个字符,称为非紧缩格式(其存储密度小)。
2,每个单元存放多个字符,称为紧缩格式(其存储密度大)。
顺序串中实现串的基本运算与顺序表的基本运算类似。
串的堆存储/变长存储结构
链串的组织形式与一般的链表类似。
*链串中的一个结点可以存储多个字符。 *通常将链串中每个结点所存储的字符个数称为结点大小。
typedef struct snode
{ char data;
struct snode *next;
} LinkStrNode;
链串只能采用单链表吗?
不一定。需要根据需要情况而定。 如果需要从某个结点出发前后查找,可以采用双链表。
如果需要快速查找尾结点,可以采用循环双链表。
2,串的模式匹配;
成功是指在目标串s中找到一个模式串t----------t是s的子串,返回t在s中的位置。
不成功则指目标串s中不存在模式串t------------t不是s的子串,返回-1。
简单匹配算法:Brute-Force简称为BF算法,亦称简单匹配算法。采用穷举的思路。BF是指暴力的意思!
算法的思路是从s的每一个字符开始依次与t的字符进行匹配。
int index(SqString s,SqString t)
{ int i=0,j=0;
while (i<s.length && j<t.length)
{ if (s.data[i]==t.data[j]) //继续匹配下一个字符
{ i++; //主串和子串依次匹配下一个字符
j++;
}
else //主串、子串指针回溯重新开始下一次匹配
{ i=i-j+1; //主串从下一个位置开始匹配
j=0; //子串从头开始匹配
}
}
if (j>=t.length)
return(i-t.length); //返回匹配的第一个字符的下标
else
return(-1); //模式匹配不成功
}
算法分析:算法在字符比较不相等,需要回溯(即i=i-j+1):即退到s中的下一个字符开始进行继续匹配。
最好情况下的时间复杂度为O(m)。最坏情况下的时间复杂度为O(n×m)。 平均的时间复杂度为O(n×m)。
3,KMP算法
KMP算法是D.E.Knuth、J.H.Morris和V.R.Pratt共同提出的,简称KMP算法。
该算法较BF算法有较大改进,主要是消除了主串指针的回溯,从而使算法效率有了某种程度的提高。
void GetNext(SqString t,int next[]) //由模式串t求next值的算法:
{ int j,k;
j=0; k=-1; next[0]=-1;
while (j<t.length-1)
{ if (k==-1 || t.data[j]==t.data[k])
{ j++; k++;
next[j]=k;
}
else k=next[k];
}
}
next[j]的含义:(1)next[j]=k,说明模式串t[j]之前有k个字符已成功匹配,下一趟应从t[k]开始匹配。
2)next[j]=-1 说明模式串t[j]之前没有任何用于加速匹配的信息,下一趟应从t的开头即j++ ð j=0开始匹配。
int KMPIndex(SqString s,SqString t)
{ int next[MaxSize], i=0, j=0;
GetNext(t,next);
while (i<s.length && j<t.length)
{
if (j==-1 || s.data[i]==t.data[j])
{ i++;
j++; //i、j各增1
}
else j=next[j]; //i不变,j后退
}
if (j>=t.length)
return(i-t.length); //返回匹配模式串的首字符
else
return(-1); //返回不匹配标志
}
算法分析:设串s的长度为n,串t长度为m。
在KMP算法中求next数组的时间复杂度为O(m),在后面的匹配中因主串s的下标不减即不回溯,比较次数可记为n,所以KMP算法平均时间复杂度为O(n+m)。 最坏的时间复杂度为O(n × m)。
补充1:串的模式匹配中next[]数组的求解
步骤(1)初始化next[1]=0 next[2]=1;
步骤(2)求next[j],令k=next[j-1]
步骤(3)S[j-1] S[k] 比较大小
= ,next[j]=k+1
!= ,k=next[k], k!=0, 返回(3);
= 0,next[j]=1
二、考试要求:
掌握字符串的两种存储结构,即定长存储结构和堆存储结构,能够在两中存储结构上实现字符串的各种运算,
掌握字符串的模式匹配运算及相应的改进算法。