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 }