本段程序实现串的存储结构是采用堆的动态分配存储表示,并实现了几乎所有常用的串的配套函数
其中逻辑性比较强的就是串的模式匹配算法,在下面的程序中,分别用BF算法和KMP算法对其进行了
实现。
#include<iostream>
using namespace std;
struct HString
{
HString()
{
ch = 0;
length = 0;
}
char * ch;//字符存储区
int length;//串长
};
void ClearString(HString & T);
//用C字符串进行初始化
void StrAssign(HString & T,char s[])
{
free(T.ch);
T.length = 0;
for(;'\0'!=s[T.length];(T.length)++);
T.ch =(char *)malloc(T.length*(sizeof(char)));
if(!T.ch) exit(0);
for(int i=0;'\0'!=s[i];i++)
{
T.ch[i] = s[i];
}
}
//串的复制
void StrCopy(HString & T,HString & S)
{
ClearString(T);
T.length = S.length;
T.ch = (char*)malloc(T.length*(sizeof(char)));
if(!T.ch) exit(0);
for(int i=0;i<T.length;i++)
{
T.ch[i] = S.ch[i];
}
}
//串的比较
int StrCompare(HString & T,HString & S)
{
for(int i=0;i<T.length&&i<S.length;i++)
{
if(T.ch[i]!=S.ch[i]) return T.ch[i]-S.ch[i];
}
return T.length - S.length;
}
//返回串的长度
int StrLength(HString & T)
{
return T.length;
}
//清空串
void ClearString(HString & T)
{
free(T.ch);
T.length = 0;
}
//连接两个串构成一个新串
void Concat(HString & T,HString & S1,HString & S2)
{
ClearString(T);
T.length = S1.length + S2.length;
T.ch = (char*)malloc(T.length*(sizeof(char)));
if(!T.ch) exit(0);
int i = 0;
for(;i<S1.length;i++)
{
T.ch[i] = S1.ch[i];
}
for(int j = 0;j<S2.length;j++,i++)
{
T.ch[i] = S2.ch[j];
}
}
//用Sub串返回S的第pos个字符起长度为len的字串Sub
bool SubString(HString & Sub,HString & S,int pos,int len)
{
if(S.length<(pos+len-1)) return false;
Sub.length = len;
Sub.ch = (char*)malloc(Sub.length*(sizeof(char)));
if(!Sub.ch) exit(0);
for(int i = 0;i<len;i++)
{
Sub.ch[i] = S.ch[pos+i-1];
}
return true;
}
/*
//串的模式匹配
//若主串S中存在和串T值相同的字串,则返回它在主串S中第pos个字符之后的第一次出现的位置,否则返回-1
*/
//算法一:BF算法
int Index_BF(HString &S,HString &T,int pos)
{
int i = pos ,j = 0;
while(i<S.length&&j<T.length)
{
if(S.ch[i] == T.ch[j])
{
i++;
j++;
}else
{
i = i-j+1;
j = 0;
}
}
if(j>=T.length) return i - T.length;
else return -1;
}
//算法二:KMP算法 --- 辅助函数(初始化并发next数组)
void Get_next(HString &T,int next[])
{
int i = 1,j;
next[0] = 0;
next[1] = 0;
j = next[1];
for(;i<T.length;)
{
if(0==j||T.ch[i] == T.ch[j])
{
if(0==j&&T.ch[i] != T.ch[j])
{next[++i] = j;}
else
{
next[++i] = ++j;
}
}
else
{
j = next[j];
}
}
}
//算法二:KMP算法 --- 实现函数
int Index_KMP(HString &S,HString &T,int pos)
{
int * next = new int[T.length];
Get_next(T,next);
int i = pos,j = 0;
for(;i<S.length&&j<T.length;)
{
if(S.ch[i] == T.ch[j])
{
j++;
i++;
}
else
{
if(0==j) i++;
else j = next[j];
}
}
if(j>=T.length)
{
return i - T.length;
}
else{
return -1;
}
}
//用V替换S中所有与T相等的不重叠的字串
//替换的前提是被替换的字符串T和替换的字符串的长度相等 Replace(str2,str3,strV);
bool Replace(HString & S,HString &T,HString &V)
{
if(T.length!=V.length) return false;
int pos =0;
while (pos<S.length)
{
pos = Index_BF(S,T,pos);
if(-1==pos) return true;
else{
for(int i = 0;i<T.length;i++)
{
S.ch[i+pos] = V.ch[i];
}
pos += V.length;
}
}
}
//在串S的第pos个字符之前插入串T
bool StrInsert(HString &S,int pos,HString &T)
{
--pos;
if(S.length<pos) return false;
HString ss;
StrCopy(ss,S);
ClearString(S);
S.length = ss.length + T.length;
S.ch = (char*)malloc(S.length*(sizeof(char)));
if(!S.ch) exit(0);
int i =0;
for(;i<pos;i++)
{
S.ch[i] = ss.ch[i];
}
for(int j=0;j<T.length;j++)
{
S.ch[i++] = T.ch[j];
}
for(;pos<ss.length;pos++)
{
S.ch[i++] = ss.ch[pos];
}
return true;
}
//从串S中删除第pos个字符起长度为len的字串
bool StrDelete(HString &S,int pos,int len)
{
if(S.length<(pos+len-1))return false;
HString ss;
StrCopy(ss,S);
ClearString(S);
S.length = ss.length - len;
S.ch = (char*)malloc(S.length*(sizeof(char)));
if(!S.ch)exit(0);
int i = 0;
for(;i<pos;i++)
{
S.ch[i] = ss.ch[i];
}
for(pos = pos+len;pos<ss.length;pos++)
{
S.ch[i++] = ss.ch[pos];
}
return true;
}
//遍历访问串中的每一个字符
void Visit(HString & T,void(*visit)(char &))
{
for(int i = 0;i<T.length;i++)
{
(*visit)(T.ch[i]);
}
}
//测试函数
void fun(char &t)
{
cout<<t;
}
int main()
{
//创建一个空串
HString str;
//用C字符串进行初始化
char c[] = "ILOVEYOU";
cout<<"用C字符串进行初始化 :str:"<<endl;
StrAssign(str,c);
//输出
Visit(str,fun);
cout<<endl;
//返回串的长度
cout<<"str串的长度是:"<<StrLength(str)<<endl;
//串的复制
HString str1;
StrCopy(str1,str);
cout<<"串的复制 str1:"<<endl;
//输出
Visit(str1,fun);
cout<<endl;
//串的比较
int s = StrCompare(str,str1);
if(s==0)
{
cout<<"str=str1"<<endl;
}
if(s>0)
{
cout<<"str>str1"<<endl;
}
if(s<0)
{
cout<<"str<str1"<<endl;
}
//连接两个串构成一个新串
HString str2;
Concat(str2,str,str1);
cout<<"连接两个串构成一个新串 str2:"<<endl;
//输出
Visit(str2,fun);
cout<<endl;
//用Sub串返回S的第pos个字符起长度为len的字串Sub
HString str3;
cout<<"用Sub串返回S的第7个字符起长度为2的字串str3: "<<endl;
SubString(str3,str,7,2);
//输出
Visit(str3,fun);
cout<<endl;
//串的模式匹配 查找子串在主串中第一次出现的位置
cout<<"BF算法:查找子串str3在主串str1中第一次出现的位置"<<endl;
int index = Index_BF(str1,str3,0);
if(-1==index)
{
cout<<"BF算法:未找到子串str3"<<endl;
}
else
{
cout<<"BF算法:查找子串str3在主串str1中第一次出现的下标为:"<<index<<endl;
}
cout<<"KMP算法:查找子串str3在主串str1中第一次出现的位置"<<endl;
int index2 = Index_KMP(str1,str3,0);
if(-1==index2)
{
cout<<"KMP算法:未找到子串str3"<<endl;
}
else
{
cout<<"KMP算法:查找子串str3在主串str1中第一次出现的下标为:"<<index2<<endl;
}
//用V替换S中所有与T相等的不重叠的字串
HString strV;
StrAssign(strV,"ZR");
cout<<"用“ZR”替换主串Str2中所有的子串str3"<<endl;
Replace(str2,str3,strV);
//输出
Visit(str2,fun);
cout<<endl;
//在串str2的第pos个字符之前插入串str3
cout<<"在串str2的第2个字符之前插入串str3"<<endl;
StrInsert(str2,2,str3);
//输出
Visit(str2,fun);
cout<<endl;
//从串Str2中删除第pos个字符起长度为len的字串
cout<<"从串Str2中删除第2个字符起长度为3的字串"<<endl;
StrDelete(str2,2,3);
//输出
Visit(str2,fun);
cout<<endl;
}