天天看点

统计字符串中单词个数

统计字符串中单词个数

要求:输入一个字符串,统计每个单词的个数。单词间用空格隔开,可多个空格,写出自己认为高效的算法。

例如:输入:I love love China

输出为:

I: 1

love: 2

China: 1

统计字符串中单词个数

首先想到的还是模拟的方法,就是用struct把出现过的单词缓存起来,然后再输入文本中遍历到新单词的时候,遍历一次struct,看这个单词是不是已经存,做相关处理。

如果输入文本中有n个字母,不重复的字母为m个, 则算法复杂度为O(nm^2) 最好情况是m =1 ,最差情况是m=n 其实现代码如下:

1 #include <stdio.h>
 2  #include <string.h>
 3   struct struct_words{
 4          char word[20];
 5          int count;
 6  };
 7   int main(){
 8          char string[100];
 9          char c;
10          struct struct_words words[20];
11          int i = 0, k = 0 , ws =0;
12  
13          for(; i < 20; i++){
14                  words[i].word[0] = '\0';
15                  words[i].count = 0;
16          }
17          puts("please input words.");
18          gets(string);
19          puts("=============开始取词================");
20  
21          i = 0;
22          do{
23                  c = string[i];
24                  if(c != ' ' && c !='\0'){
25                          words[k].word[ws] = c;
26                          words[k].count = 1;
27                          ws ++;
28                  }else{
29                          words[k].word[ws] = '\0';
30                          ws = 0;
31                          k ++;
32                  }
33                  i ++;
34          }while(c!='\0');lda
35  
36  
37          puts("=========== 合并相同的单词 ==============");
38          for(i = 0; words[i].word[0] != '\0' ; i++){
39                  puts(words[i].word);
40                  if( words[i].count >= 1)
41                  for(k = i; words[k].word[0] != '\0'; k++){
42                          if(strcmp(words[i].word, words[k].word) == 0
43                             && words[k].count == 1){
44                                  words[k].count --;
45                                  words[i].count ++;
46                          }
47                  }
48          }
49  
50          puts("=============== End ==============");
51          for(i = 0;words[i].word[0] != '\0' ;i++){
52                  if(words[i].count != 0 )
53                          printf("%s:\t\t%d\n",words[i].word, words[i].count);
54          }
55          return(0);
56  }      

然后呢,做一下优化,恩路是遍历用户的输入文本是必须的,但是,单词的缓存和出现次数的统计是可以使用hash算法来优化的,借用hash算法的特性,使复杂度立刻就降低到了 O(n),实现代码如下:

1 #include <stdio.h>
 2 #include <string.h>
 3 #define N 100
 4 
 5 struct struct_words{
 6     char word[100];
 7     int count;
 8 };
 9 
10 int hash(char* key)
11 {
12      unsigned long h=0;
13       while(*key)
14            {   
15                  h=(h<<4)+*key++;
16                    unsigned long g=h & 0xF0000000L;
17                      if(g)
18                             h^=g>>24;
19                        h&=~g;
20                         }   
21        return h&N;
22 }
23 int main(){
24     char string[1000];
25     char current_word[100];
26     char c;
27     struct struct_words words[200]; 
28     int i = 0, k = 0 , ws =0 , key;
29     int keys[100];
30 
31     for(; i < 200; i++){
32         words[i].word[0] = '\0';
33         words[i].count = 0;
34     }   
35     puts("=============输入一些单词,用空格隔开================");
36     gets(string);
37 
38     i = 0;
39     do{ 
40         c = string[i];
41         //如果第一个单词前有空格,跳过去
42         if( ws == 0  && c == ' ') {i++ ; continue;}
43         if(c != ' ' && c !='\0'){
44             current_word[ws] = c;
45             ws ++; 
46         }else{
47             current_word[ws] = '\0';
48             key = hash(current_word);
49             if(words[key].count == 0){ 
50                 strcpy(words[key].word, current_word);
51                 keys[k] = key;
52                 k++;
53             }   
54             words[key].count ++; 
55             ws = 0;
56         }
57     i ++;
58     }while(c != '\0');
59 
60     printf("%d" ,k);
61     puts("===============打印結果 ==============");
62     for(i = 0 ; i < k ;i++){
63             printf("%s:\t\t%d\n",words[keys[i]].word, words[keys[i]].count);
64     }
65     puts("=============== End ==============");
66     return 0;
67 }