问题

统计输入中每个单词的出现次数(词频统计)

算法分析

可用两种方式构建包括所有单词的表:

  • 使用一个有序的链表
  • 使用二叉树

有序链表策略
每读入一个单词使用折半查找算法在有序表中查找单词,如果找到,则相应次数加1;否则将读入单词插入到有序表中相应位置(插入后有序表仍有序)。

二叉树表策略
每读入一个单词从树根节点开始查找,如果找到,则相应次数加1;否则,如果比该节点小,则转到其左子树开始查找,如果比该节点大,则转到其右子树开始查找;如果该节点下没有节点,则将读入单词插入到该节点下相应位置。

算法实现(二叉树)

若输入:

C language book study pascal statement buy

则生成如下树:

词频统计_词频统计

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define
#define
#define


struct tnode {
char *word;
int count;
struct tnode *left;
struct tnode *right;
};
struct tnode *tree(struct tnode *p, char *w);
struct tnode *talloc( );
char *strsave(char *s);
void treeprint(struct tnode *p);
void deleteTree(struct tnode *root);
char getword(char *w, int lim);
char type( int c);

int main( )
{
struct tnode *root;
char word[MAXWORD];
int t;

root = NULL;
while((t = getword(word, MAXWORD)) != EOF)
if( t == LETTER)
root = tree(root, word);
treeprint(root);
deleteTree(root);
return 0;
}

struct tnode *tree(struct tnode *p, char *w)
{
int cond;
if( p == NULL ) {
p = talloc( );
p->word = strsave(w);
p->count = 1;
p->left = p->right = NULL;
}
else if((cond = strcmp(w, p->word)) == 0)
p->count ++;
else if ( cond < 0 )
p->left = tree(p->left, w);
else
p->right = tree(p->right, w);
return ( p );
}

struct tnode *talloc( )
{
return (( struct tnode *)malloc(sizeof(struct tnode )));
}

char *strsave(char *s)
{
char *p;
if((p = (char*)malloc(strlen(s)+1)) != NULL)
strcpy(p, s);
return ( p );
}

void treeprint( struct tnode *p)
{
if(p != NULL) {
treeprint(p->left);
printf("%4d%s\n",p->count,p->word);
treeprint(p->right);
}
}

char getword(char *w, int lim)
{
int c, t;
if(type(c = *w++ = getchar( )) != LETTER){
*w = '\0';
return ( c);
}
while(--lim > 0) {
t = type(c = *w++ = getchar( ));
if( t != LETTER && t != DIGIT){
ungetc(c,stdin);
break;
}
}
*(w-1) = '\0';
return ( LETTER);
}

char type(int c) /* return type of ASCII character */
{
if( c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
return ( LETTER );
else if ( c >= '0' && c <= '9')
return ( DIGIT );
else return (c);
}
void deleteTree(struct tnode *root)
{
if(root->left!=NULL)
deleteTree(root->left);
if(root->right!=NULL)
deleteTree(root->right);

free(root->word);
free(root);
}