79 子字符串排序

问题描述 :

 编程对字符串中的子串按字典序输出。子串的形成方法为:从原始字符串开始,依次去掉开头字符形成新的子串。

例如,字符串"grain" 的子串如下所示(依次去掉g,r,a,i):

grain、rain、ain、in、n

按字典序排列为:

ain

grain

in

n

rain

 

输入说明 :

输入有多行,每行一个字符串,每个字符串的长度大于0小于等于10,字符串中不包含空格。

 

输出说明 :

 对每个字符串,按字典序输出所有子串。

行首与行尾不包含多余空格,也不包含多余空行。

 

输入范例 :

grain
123cba

 

输出范例 :

ain
grain
in
n
rain
123cba
23cba
3cba
a
ba
cba

 

 

解决思路:首先建立二维char型数组,每一行存储一个字符串,然后通过strcmp()+冒泡排序对结果集进行一趟排序。

缺点:占用空间大。

优点:思路简单,易于实现

代码如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <math.h>
 4 #include <string.h>
 5 
 6 char str[20];
 7 char str2[20];
 8 
 9 char res[20][20];
10 
11 char temp[20];
12 int main(){
13     int len = 0;
14     int res_len = 0;
15     int i,j;
16     while(scanf("%s",str)!=EOF){
17         res_len = 0;
18         len = strlen(str);
19         for(i=0;i<=len-1;i++){
20             strcpy(&res[res_len][0],str+i);
21             res_len++;
22         }
23 
24         for(i=res_len-2;i>=0;i--){
25             for(j=0;j<=i;j++){
26                 if(strcmp(&res[j][0],&res[j+1][0])>0){
27                     strcpy(temp,&res[j+1][0]);        
28                     strcpy(&res[j+1][0],&res[j][0]);    
29                     strcpy(&res[j][0],temp);
30                 }
31             }
32         }
33         
34         for(j=0;j<res_len;j++){
35             printf("%s\n",res[j]);
36         }
37     }
38     return 0;
39 }

 

 

解决思路二:在思路一种,我们建立了二维数组,占用空间大,有没有别的办法解决呢?

我们来思考,对于一个字符串数组,如:"acdb";产生的子串如下:

acdb,cdb,db,b

那么经过排序后应该是:acdb、b、cdb、db;

如果我们不想另外开辟空间存储新产生的字符串的话,我们可以建立一个索引,该索引存储的是每个字符串的输出顺序。

对于字符串:acdb来说,简历一个int num[4]={0,1,2,3};

下标0,1,2,3代表每个字符串的输出顺序,num[i]代表第i次输出的字符串str+num[i];

也就是我们的最后输出模型是这样的,如下:

1         for(i=0;i<len;i++){
2             printf("%s\n",str+num[i]);
3         }

  那么这个问题就变为,如何根据字符串的大小调整索引num数组?(索引数组中存储的相当于是字符串的一种标记-->指针)

  对字符串本身采用冒泡排序的比较,每次比较更改输出顺序索引num数组。核心代码如下:

1         for(i=len-2;i>=0;i--){//冒泡排序
2             for(j=0;j<=i;j++){
3                 if(strcmp(str+num[j],str+num[j+1])>0){//需要进行调整
4                     temp =     num[j+1];
5                     num[j+1] = num[j];
6                     num[j] = temp;
7                 }
8             }
9         }

默认输出顺序索引:

i      0  1  2  3

num[i]:    0  1  2  3

str+num[i]这是默认的输出顺序,

str产生的子串集合正好为长度为strlen(str)的数组,数组的默认内容是str+num[i],采取冒泡排序更改输出顺序索引。

 

完整代码:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <math.h>
 4 #include <string.h>
 5 
 6 
 7 
 8 char str[20];
 9 
10 
11 int num[20];
12 int main(){
13     
14     int i,j,temp,len;
15     while(scanf("%s",str)!=EOF){
16         len = strlen(str);
17         for(i=0;i<len;i++){
18             //初始化输出的序号(先后顺序)
19             num[i]=i;
20         }
21 
22         for(i=len-2;i>=0;i--){//冒泡排序
23             for(j=0;j<=i;j++){
24                 if(strcmp(str+num[j],str+num[j+1])>0){//需要进行调整
25                     temp =     num[j+1];
26                     num[j+1] = num[j];
27                     num[j] = temp;
28                 }
29             }
30         }
31 
32         for(i=0;i<len;i++){
33             printf("%s\n",str+num[i]);
34         }
35     }
36 
37     return 0;
38 }

 

 

posted @ 2020-03-07 18:33  focusDing  阅读(454)  评论(1编辑  收藏  举报