数据结构习题及答案与实验指导串4.docx
- 文档编号:29760772
- 上传时间:2023-07-26
- 格式:DOCX
- 页数:17
- 大小:48.87KB
数据结构习题及答案与实验指导串4.docx
《数据结构习题及答案与实验指导串4.docx》由会员分享,可在线阅读,更多相关《数据结构习题及答案与实验指导串4.docx(17页珍藏版)》请在冰豆网上搜索。
数据结构习题及答案与实验指导串4
第4章串
串是每个数据仅由一个字符组成的一种特殊的线性表,它在计算机文字编辑、词法分析等方面有着广泛的应用。
本章通过对串的概念、串的存储方法和串上基本运算实现的介绍,要求掌握串这种特殊线性结构的存储和基本算法实现。
重点提示:
●串与线性表的关系
●串的两种存储表示(顺序存储、链式存储)
●串的基本运算
●串的模式匹配算法
4-1重点难点指导
4-1-1相关术语
1.串
要点:
零个或多个字符组成的有限序列。
2.串的长度
要点:
串中所包含字符的个数。
3.空串
要点:
长度为零的串。
4.空白串
要点:
仅由一个或多个空格组成的串。
5.子串
要点:
串中任意个连续字符组成的子序列。
6.主串
要点:
包含子串的串。
4-1-2串的基本运算
1.StrLength(s):
求串长。
即求串s的长度。
2.StrAssign(s,t):
串复制。
即将串t复制到串s中。
3.StrConcat(s,t):
串连接。
即将串t复制到串s的末尾,构成一个新串。
4.StrCom(s,t):
串比较。
即比较串s和串t的大小,若s>t,返回正数;若s=t,返回0;若s 5.Substr(S,i,j): 求子串。 即从串S的第i个字符起连续取j个字符构成的子串。 6.StrInsert(S,i,T): 串插入。 即将串T插入到串S的第i个字符之后。 7.StrDelete(S,i,j): 串删除。 即从串S的第i个字符起连续删除j个字符。 8.StrIndex(S,T): 串匹配,也称串定位。 即当串S中存在与串T相等的子串时,则返回第一个子串T在串S中第一个字符的序号,否则返回0。 通常称T为模式串,S为主串。 9.StrRep(S,T,R): 串替换。 即用子串R替换串S中的所有子串T。 4-1-3串的存储结构 1.顺序存储 (1)特点 ①数据元素的存储与顺序表相似。 ②每个数据元素的类型是字符型。 ③也可直接采用一维字符数组存放。 (2)存储表示 ①定义顺序串的静态存储分配类型 方式1: #defineMaxStrSize256//定义字符串的最大长度 typedefstruct{ charch[MaxStrSize]; intlength; }SeqString; 特点: 便于获取串的长度;字符串最大长度固定,对字符串的存储可能产生冗余或溢出现象。 方式2: typedefcharSeqString[MaxStrSize]; 特点: 简单易实现;字符串最大长度固定,对字符串的存储可能产生冗余或溢出现象。 ②定义顺序串的动态存储分配类型 方式1: typedefstruct{ char*ch; intlength; }HString; 特点: 便于获取串的长度;字符串长度可依据具体情况获取,不会出现冗余或溢出现象。 方式2: typedefchar*String; 特点: 简单易实现;字符串长度可依据具体情况获取,不会出现冗余或溢出现象。 (3)存储示意 以静态方式1定义SeqString*S为例,在*S中存放字符串“abcde”,其存储示意如图4-1所示。 图4-1串的顺序存储示意 其中S->length=5。 2.链式存储 (1)特点 ①数据元素的存储与不带头结点的单链表相似。 ②每个结点的数据域均为字符型。 (2)存储表示 ①简单链式存储 typedefstructnode{ chardata; structnode*next; }LinkStrNode,*LinkString; 特点: 便于字符串的插入、删除和连接等操作;存储空间冗余较大。 ②块链式存储 #defineNodeSize8 typedefstructnode{ chardata[NodeSize]; structnode*next; }LinkStrNode,*LinkString; 特点: 结点内用一维数组存储字符串,结点间用指针连接;减少了字符串存储时存储空间的冗余;给字符串中的插入、删除等操作带来不便。 (3)存储示意 以定义LinkString*S为例,在*S中存放字符串“abcde”,其存储示意如图4-2所示。 (a)图为简单链式存储的示意,(b)图为块链式存储的示意(NodeSize=3)。 图4-2串的链式存储示意 其中,图4-2(a)所示的存储S->data='a',S->next为第二个结点的地址;图4-2(b)的存储S->data[0]='a',S->data[1]='b',S->data[2]='c',S->next为第二个结点的地址。 3.串的堆存储 (1)特点 ①将串名与串值分开存储,串名存储在索引表中,串值存储在堆空间中。 ②串名通过索引表对应到堆空间中的串值。 ③索引表的形式可以有多种。 ④可以根据每个字符串的长度动态地在堆空间中申请相应大小的存储空间。 (2)堆空间的存储表示 堆空间为: charstore[SMAX+1];//SMAX为能存储足够多串的内存空间大小 自由区指针: intfree;//free为堆空间中未使用区域的首位置 (3)索引表的存储表示 ①带串长度的索引表 typedefstruct{ charname[MAXNAME];//串名 intlength;//串长 cha*stradr;//起始地址 }LNode; 特点: 便于取得串的长度。 ②带末尾指针的索引表 typedefstruct{ charname[MAXNAME];//串名 charstradr,enadr;//起始地址,末尾地址 }ENode; 特点: 便于取得串的尾部。 ③带特征位的索引表 typedefstruct{ charname[MAXNAME];//串名 inttag;//特征位 union{//起始地址或串值 char*stradr;//起始地址 charvalue[4];//串值 }uval; }TNode; 特点: 对于短字符串的存取既节省空间又可快速读取。 4-1-4字符串匹配算法实现 1.用串的其他运算构造字符串匹配的运算Index[S,T]. 【算法思想】利用Length运算求出S、T两串的长度,然后再用Substr运算从S的第一个字符开始依次取得与T串长度相同的子串,调用Equal运算,将该子串与T串比较,若相等,则匹配成功,返回T串在S串中第一个字符的位置;否则匹配失败,返回0。 【算法】intindex(strings,t){ inti,slen,tlen; i=1; slen=length(s); tlen=length(t);//求串s、t的长度 while((i+tlen-1<=slen)&&(! Equal(Substr(s,i,tlen),t))) i++;//往后匹配 if(i+tlen<=slen) returni;//匹配成功返回i的值 else return0;//匹配不成功返回0 } 2.顺序串上的实现 【算法思想】设T为主串,P为模式串,i为主串中当前匹配子串的首位置,k为主串中当前匹配字符的位置,j为模式串中当前匹配字符的位置。 比较T.ch[k]和P.ch[j]的值。 ①若T.ch[k]=P.ch[j],则k加1,j加1,均移向T和P的下一个字符,继续比较。 若到P串结束前一直相等,则匹配成功。 ②若T.ch[k]≠P.ch[j],则说明主串中当前i开始的子串与P不匹配,i加1取下一个子串,置k等于i,j等于0,重新将模式串与主串中的子串比较。 ③当主串中无法取得与模式串长度相等的子串时(即i>n-m时),则匹配失败。 【算法】intNaiveStrMatch(SeqStringT,SeqStringP){ //找模式串P在目标T中首次出现的位置,成功时返回第1个有效位移,否则返回-1 inti,j,k; intm,n; m=P.length;//模式串长度 n=T.length;//目标串长度 for(i=0;i<=n-m;i++){//0≤i≤n-m是合法的位移 j=0; k=i;//下面用while循环判定i是否为有效位移 while(j k++; j++; } if(j==m)//即T[i..i+m-1]=P[0..m-1] returni;//i为有效位移,否则考查下一个位移 } return-1;//找不到有效位移,匹配失败 } 3.链串上的实现 【算法思想】由于是链式串,所以对元素的存储表示与顺序串不同,在链式串中不是用下标指示元素,而是用指针指示元素。 在算法中用到的指针变量shift、t和p分别相当于顺序串匹配算法中的i、k和j的作用。 【算法】LinkStrNode*LinkStrMath(LinkStringT,LinkStringP){ //在链串上求模式串P在目标T中首次出现的位置 LinkStrNodeshift,*t,*p; shift=T;//shift表示位移 t=shift; p=P; while(t&&p) if(t->data==p->data){//继续比较后续结点中的字符 t=t->next; p=p->next; } else{//已确定shift为无效位移 shift=shift->next;//模式右移,继续判定shift是否为有效位移 t=shift; p=P; } if(p==NULL) returnshift;//匹配成功 else returnNULL;//匹配失败 } 4-2典型例题解析 4-2-1字符串的基本运算题 1.设有A='',B='mule',C='old',D='my',计算下列运算的结果(注: “A+B”是Concat的简写)。 (a)A+B(b)B+A(c)D+C+B(d)SubStr(B,3,2) (e)SubStr(C,1,0)(f)StrLength(A)(g)StrLength(D)(h)StrIndex(B,D) (i)StrIndex(C,"d")(j)StrInsert(D,2,C)(k)StrInsert(B,I,A)(l)StrDelete(B,2,2) (m)StrDelete(B,2,0)(n)StrRep(C,2,2,"k") 【解答】 (a)A+B="#mule";(b)B+A="mule#" (c)D+C+B="myoldmule"(d)SubStr(B,3,2)="le" (e)SubStr(C,1,0)=""(f)StrLength(A)=1 (g)StrLength(D)=2(h)StrIndex(B,D)=0 (i)StrIndex(C,"d")=3(j)StrInsert(D,2,C)="myldy" (k)StrInsert(B,I,A)="m#ule"(l)StrDelete(B,2,2)="me" (m)StrDelete(B,2,0)="mule"(n)StrRep(C,2,2,"k")="ok" 2.假设有如下的串说明: charsl[30]="Stocktom,CA",s2[30]="March5,1999",s3[30]; (1)调用函数strCmp(s1,s2)的返回值是什么? (2)调用函数strCmp(&s1[5],"ton")的返回值是什么? (3)调用函数Strlength(StrConcat(s1,s2))的返回值是什么? 【解答】 (1)正数,表示s1大于s2。 (2)负数,表示“tom,CA”小于“ton”。 (3)23,即为s1与s2连接后的长度。 4-2-2算法设计题 1.在顺序串上实现串的判等运算Equal(S,T)。 【算法】 intEqual(HStrings,t){ //串S、T为顺序存储结构 inti; if(s.length! =t.length)//判断串S、T长度是否相等 return0;//两串不相同 else{ i=0; while((i i++;//跳过前面相同元素 if(i>=s.length) return1;//i>s.length表示两串相同,返回1,否则返回0 else return0; } } 2.在链串上实现串的判等运算Equal(S,T)。 【算法】 intEqual(LinkStrLists,t){ //串s、t为链式存储结构 LinkStrListp1,p2; pl=s; p2=t; while((pl! =NULL)&&(p2! =NULL)&&(pl->ch==p2->ch)){ pl=pl->next; p2=p2->next; }//p1、p2元素值相等,p1、p2后移 if((pl==NULL)&&(p2==NULL)) return1;//若p1、p2同时为空指针时表示两串相同返回1,否则返回0 else return0; } 3.若X和Y是用结点大小为1的单链表表示的串,设计一个算法找出X中第一个不在Y中出现的字符。 【分析】将X串的结点值依次与Y串中的结点值比较,若找到第一个不在Y中出现的结点,则查找成功,返回该值,否则用一个特殊符号“$”表示X中的结点均在Y中出现过。 【算法】 charlocate(LinkStringX,LinkStringY){ //串用无头结点的单链表存储 LinkStringp,q; p=X;//指向X串第一个结点 while(p! =NULL){ q=Y;//在Y表中查找是否有p->data元素 while((q! =NULL)&&(q->data! =p->data)) q=q->next;//子串后移 if(q==NULL) returnp->data;//查找成功 p=p->next//查找X表中下一个元素 } return'$'; } 4.若S和T是用结点大小为1的单链表存储的两个串,设计一个算法将串S中首次与串T匹配的子串逆置。 【分析】本算法的实现分3部分: ①链串中的匹配; ②匹配成功后将子串逆置; ③将逆置后的子串连到原串中。 其中,串匹配前面已介绍过,这里主要说明串逆置的过程。 若t是所找到的子串,则prior指向子串t的第一个结点的直接前趋,p指针指向子串t最后一个结点的直接后继,如图4-3所示。 为了对串t逆置,从子串t第一个结点开始设置3个指针q、r、u,再依次将r所指向结点的next域指向它的前一个结点,即将r->next=q,再将q、r、u右移而q=r;r=u;u=r->next直到p=r时逆置完毕,逆置后的结果如图4-4所示。 而逆置后tl结点的直接后继是*p,*prior的直接后继是tn。 图4-3串找子串t的示意图 图4-4子串t逆置的示意图 【算法】 intinvertsubstr(LinkStrings,t){ //s、t均带头结点 LinkStrNode*p,*prior,*t1; LinkStrNode*r,*u,*q; prior=s; p=prior->next;//prior为p的前驱 tl=t->next; if((p==NULL)||(tl==NULL)){ cout<<"不匹配"; return0; }//s、t两串至少有一个为空串,返回 while((p! =NULL)&&(tl! =NULL)) if(p->data==tl->data){ p=p->next; tl=tl->next; }//继续往后比较 else{ prior=prior->next;//匹配不成功,向后移 p=prior->next; tl=t->next; } if(tl! =NULL){ cout<<"不匹配"; return0; } else{ q=prior->next; r=q->next;//匹配成功,开始逆置 while(r! =p){ u=r->next; r->next=q; q=r; r=u; } prior->next->next=p;//将逆置后的子串连到原串中 prior->next=q; } } 4-3课后习题选解 1.利用C的库函数strlen、strcpy和strcat写一个算法voidStrInsert(char*S,char*T,inti),将串T插入到S的第i个位置上。 若i大于S的长度,则插入不执行。 voidstrinsert(char*s,char*t,inti){ if(i<=strlen(s)){ strcopy(s+i,r); s[i]='\0'; strcat(s,t); strcat(s,r); } } 2.利用C的库函数strlen、strcpy(或strncpy)写一个算法voidStrDelete(char*S,inti,intm),删除串S中从位置i开始连续的m个字符。 若i≥strlen(S),则没有字符被删除;若i+m≥strlen(S),则S中从位置i开始直至末尾的字符均被删去。 voidstrdelete(char*s,intm){ inti,k; if(i if(i+m>=strlen(s)) s[i]='\0'; else{ for(k=i+m;s[k]! ='\0';k++) s[k-m]=s[k]; s[k]='\0'; } } 3.采用顺序结构存储串,编写一个函数,求串s和串t的一个最长的公共子串。 【提示】需要采用三重循环来实现。 typedefstruct{ char*data; intlen; }string; voidmaxsubstr(char*s,char*t,char*r){ //求S和T的最长公共子串,存储在串变量r中。 inti,j,k,num,maxnum,index; maxnum=0; index=0; i=0; while(i j=0; while(j if(s->data[i]==t->data[j]){ num=1; for(k=1;s->data[i+k]==t->data[j+k];k++) num++; if(num>maxnum){ index=i; maxnum=num; } j=j+num; i=0; } else j++; i++; } for(i=index,j=0;i r->data[j]=s->data[i]; } 4.采用顺序存储结构存储串,编写一个函数计算一个子串在一个字符串中出现的次数,如果该子串不出现则为0。 intcount(char*s,char*t){ inti,c,j; i=0; c=0; while(i j=strindex_KMP(s,t,i,next); if(j! =0) c++; i=i+strlen(t); } returnc; }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 习题 答案 实验 指导