anyview 数据结构习题集 第4章答案
4.10③ 编写对串求逆的递推算法。
要求实现以下函数:
void Reverse(StringType &s);
/* Reverse s by iteration. */
StringType是串的一个抽象数据类型,它包含以下6种基本操作:
void InitStr(StringType &s);
// 初始化s为空串。
void StrAssign(StringType &t, StringType s);
// 将s的值赋给t。s的实际参数是串变量。
int StrCompare(StringType s, StringType t);
// 比较s和t。若s>t,返回值>0;若s=t,返回值=0;若s<t,返回值<0。
int StrLength(StringType s);
// 返回s中的元素个数,即该串的长度。
StringType Concat(StringType &s, StringType t);
// 返回由s和t联接而成的新串。
StringType SubString(StringType s, int start, int len);
// 当1<=start<=StrLength(s)且0<=len<=StrLength(s)- start+1时,
// 返回s中第start个字符起长度为len的子串,否则返回空串。
// 注意,不要使用 ” s = ” 的形式为 StringType 类型的变量赋值 ,
// 而要使用 StrAssign 函数!!!
void Reverse(StringType &s) /* Reverse s by iteration. */ { StringType temp; int i=StrLength(s); InitStr(temp); //初始化空串 //经测试,StrAssign(temp,'')错误~~原因未知 while(i){ Concat(temp,SubString(s,i,1)); --i; //经测试,while(i--)就回出错~ } StrAssign(s,temp); }
4.12③ 编写一个实现串的置换操作Replace(&S,T,V)的算法。
要求实现以下函数:
void Replace(StringType &S, StringType T, StringType V);
/* 以串 v 置换串 s 中出现的所有和串 t 相同的非空串 */
StringType是串的一个抽象数据类型,它包含以下6种基本操作:
void InitStr(StringType &s);
// 初始化s为空串。
void StrAssign(StringType &t, StringType s);
// 将s的值赋给t。s的实际参数是串变量。
int StrCompare(StringType s, StringType t);
// 比较s和t。若s>t,返回值>0;若s=t,返回值=0;若s<t,返回值<0。
int StrLength(StringType s);
// 返回s中的元素个数,即该串的长度。
StringType Concat(StringType &s, StringType t);
// 返回由s和t联接而成的新串。
StringType SubString(StringType s, int start, int len);
// 当1<=start<=StrLength(s)且0<=len<=StrLength(s)- start+1时,
// 返回s中第start个字符起长度为len的子串,否则返回空串。
// 注意,不要使用 ” s = ” 的形式为 StringType 类型的变量赋值 ,
// 而要使用 StrAssign 函数!!!
void Replace(StringType &S, StringType T, StringType V) /* 以串 v 置换串 s 中出现的所有和串 t 相同的非空串 */ { int i=1,S_Len,T_Len,V_Len; StringType r; S_Len=StrLength(S); T_Len=StrLength(T); V_Len=StrLength(V); InitStr(r); while(i<=S_Len-T_Len+1){ StrAssign(r,SubString(S,i,T_Len)); if(0==StrCompare(r,T)){ InitStr(r); Concat(r,SubString(S,1,i-1)); Concat(r,V); Concat(r,SubString(S,i+T_Len,S_Len-T_Len-i+1)); StrAssign(S,r); i+=V_Len; S_Len=StrLength(S);//注意要更新S的长度! } else{ ++i; } } }
4.13③ 编写算法,从串s中删除所有和串t相同的子串。
要求实现以下函数:
void DelSubString(StringType &scrStr, StringType subStr);
/* Remove all substring matching ‘subStr’ from ‘scrStr’. */
StringType是串的一个抽象数据类型,它包含以下6种基本操作:
void InitStr(StringType &s);
// 初始化s为空串。
void StrAssign(StringType &t, StringType s);
// 将s的值赋给t。s的实际参数是串变量。
int StrCompare(StringType s, StringType t);
// 比较s和t。若s>t,返回值>0;若s=t,返回值=0;若s<t,返回值<0。
int StrLength(StringType s);
// 返回s中的元素个数,即该串的长度。
StringType Concat(StringType &s, StringType t);
// 返回由s和t联接而成的新串。
StringType SubString(StringType s, int start, int len);
// 当1<=start<=StrLength(s)且0<=len<=StrLength(s)- start+1时,
// 返回s中第start个字符起长度为len的子串,否则返回空串。
// 注意,不要使用 ” s = ” 的形式为 StringType 类型的变量赋值 ,
// 而要使用 StrAssign 函数!!!
void DelSubString(StringType &scrStr, StringType subStr) /* Remove all substring matching 'subStr' from 'scrStr'. */ { int S_Len,T_Len,i=1; StringType temp; InitStr(temp); S_Len=StrLength(scrStr); T_Len=StrLength(subStr); while(i<=S_Len-T_Len+1){ StrAssign(temp,SubString(scrStr,i,T_Len)); if(0==StrCompare(temp,subStr)){ InitStr(temp); Concat(temp,SubString(scrStr,1,i-1)); Concat(temp,SubString(scrStr,T_Len+i,S_Len-T_Len-i+1)); StrAssign(scrStr,temp); S_Len=StrLength(scrStr); } else{ ++i; //注意这里删除substr后i不变!! } } }
4.17③ 编写算法,实现串的基本操作Replace(&S,T,V)。
要求采用教科书4.2.1节中所定义的定长顺序存储表示,
但不允许调用串的基本操作。
要求实现以下函数:
Status Replace(SString& s, SString t, SString v);
/* 用串v替换串s中所有和串t匹配的子串。 */
/* 若有与t匹配的子串被替换,则返回TRUE;*/
/* 否则返回FALSE */
定长顺序串SString的类型定义:
typedef unsigned char SString[MAXSTRLEN+1];
/* s[0] is the string’s length */
Status Replace(SString& s, SString t, SString v) /* 用串v替换串s中所有和串t匹配的子串。 */ /* 若有与t匹配的子串被替换,则返回TRUE;*/ /* 否则返回FALSE */ /*这道题要注意的是顺序串元素的移动*/ { //没通过,强烈怀疑测试数据有问题!!! int flag=0,i,j,k,pos,step; step=t[0]-v[0];//得到两个串的长度差 for(i=1;i<=s[0]-t[0]+1;++i){//依次匹配串 for(pos=i,j=1;j<=t[0];++pos,++j){ if(s[pos]!=t[j]){//此处若写成 pos++和j++,那么下面t[0]<j+1 break; } //如果不匹配,则退出循环 } if(t[0]<j){//如果匹配成功 if(0==step){//判断是否需要串元素 for(j=1,k=i;j<=v[0];++k,++j){ s[k]=v[j]; } } else if(step<0){//串t长度小于模式串的情况 for(k=s[0];k>=i;--k){ s[k-step]=s[k]; } for(j=1,k=i;j<=v[0];++k,++j){ s[k]=v[j]; } } else {//t的长度大于模式串的情况 for(k=pos;k<=s[0];++k){ //此处因为抄了前面的代码,所以没有注意到细节,导致 结果错误,已改正 s[k-step]=s[k]; } for(j=1,k=i;j<=v[0];++k,++j){ s[k]=v[j]; } } flag=1;//记录成功置换 i+=v[0]-1;//i向后移动 s[0]+=-step;//step为正时s[0]减小,step为负时,s[0]增加,故 } } if(flag){ return TRUE; } return FALSE; }
4.20③ 编写算法,从串s中删除所有和串t相同的子串。
要求实现以下函数:
Status DelSub(SString &s, SString t);
/* 从串s中删除所有和串t匹配的子串。 */
/* 若有与t匹配的子串被删除,则返回TRUE;*/
/* 否则返回FALSE */
定长顺序串SString的类型定义:
typedef unsigned char SString[MAXSTRLEN+1];
/* s[0] is the string’s length */
Status DelSub(SString &s, SString t) /* 从串s中删除所有和串t匹配的子串。 */ /* 若有与t匹配的子串被删除,则返回TRUE;*/ /* 否则返回FALSE */ { int i,j,pos,flag=0; for(i=1;i<=s[0]-t[0]+1;++i){ for(j=1,pos=i;j<=t[0];++j,++pos){ //模式串匹配 if(s[pos]!=t[j]){ break; } } if(j>t[0]){//删除操作--移动串元素 for(;pos<=s[0];++pos){ s[pos-t[0]]=s[pos]; } s[0]-=t[0]; flag=1; //标记成功删除 --i; //关键点!!容易出错的地方,删除了元素之后, //i保持不变,因循环会加1,故 } } if(flag){ return TRUE; } else{ return FALSE; } }
4.24③ 采用教科书4.2.2节中所定义的堆分配存储
表示。试写一算法,在串的堆存储结构上实现串基
本操作Concat(&T, s1, s2)。
要求实现以下函数:
Status Concat(HString &S, HString S1, HString S2)
/* 用S返回由S1和S2联接而成的新串 */
堆串HString的类型定义:
typedef struct {
char *ch; // 若是非空串,则按串长分配存储区,否则ch为NULL
int length; // 串长度
} HString;
//通过了忘记保存.... //并不难,不解释
4.30⑤ 假设以定长顺序存储结构表示串,试设计
一个算法,求串s中出现的第一个最长重复子串及
其位置,并分析你的算法的时间复杂度。
要求实现以下函数:
void CommonStr(SString s, SString &sub, int &loc);
/* 求串s中出现的第一个最长重复子串sub及其位置loc */
定长顺序串SString的类型定义:
typedef unsigned char SString[MAXSTRLEN+1];
/* s[0] is the string’s length */
//目前对此题没有好的解法,占位