利用二叉搜索树来实现输入文本的单词统计
2012-05-01 16:45
405 查看
这里有个题目,输入一个文本(纯英文),我们要能够得到文本中每个单词出现的个数,并且按照字典顺序输出。
解决这个题目可以利用二叉搜索树,这是一个比较好理解的方法,它将整个文本单词分解从根部(root)延伸,当输入的
单词比上一个大,就连接到此节点的右边,若小,则连接到左边,这样就可以轻易的将他们有序的连接了。
首先,我们需要一个结构体来提供储存单词和单词出现的次数,定义如下:
然后我们需要一个插入函数,这是一个递归版本的插入函数,talloc只是malloc的替代,是一个自定义函数,后面会给出
其实现代码。
在插入函数中我们有一个strdup函数,它用于将字符串复制给一个动态字符串并返回此动态字符串,
由于strlen只能算出字符串除了‘\0’之外的字符数,所有申请动态内存时应该用strlen(s)+1。下面给出
此函数的实现:
然后我们需要一个打印这个二叉树的函数,同样采用递归;
大家应该注意到了,我们还有getword、getch、ungetch函数为实现,下面将对其一一解释:
第一个:getch函数和ungetch函数
顾名思义,这两个的作用一个是获取字符,一个是压回字符,其实这是堆栈的结构,我们需要
一个足够大的数组来实现静态数组的堆栈:
#define BUFSIZE 100//缓冲区的大小
char buf[BUFSIZE];//字符缓冲区
int bufp = 0;//缓冲区中的下一个位置
下面给出这两个函数的实现:
最后,我们来看一看getword函数,这个函数将从缓冲区中获取一个字符,这个字符开头必须是字母,
它返回的字符是输入字符串的第一个字符,代码如下:
这样我们就可以轻易的实现的文本中的单词统计了。
附录(完整代码):
解决这个题目可以利用二叉搜索树,这是一个比较好理解的方法,它将整个文本单词分解从根部(root)延伸,当输入的
单词比上一个大,就连接到此节点的右边,若小,则连接到左边,这样就可以轻易的将他们有序的连接了。
首先,我们需要一个结构体来提供储存单词和单词出现的次数,定义如下:
struct tnode { char *word; //记录单词 int count; //记录次数 struct tnode *left; //左节点 strcut tnode *right; //右节点 };
然后我们需要一个插入函数,这是一个递归版本的插入函数,talloc只是malloc的替代,是一个自定义函数,后面会给出
其实现代码。
struct tnode *addTree(struct tnode *p,char *w) { int cond; if(p == NULL) { p = talloc(); p->word = strdup(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 = addTree(p->left,w); else p->right = addTree(p->right,w); return p; }
在插入函数中我们有一个strdup函数,它用于将字符串复制给一个动态字符串并返回此动态字符串,
由于strlen只能算出字符串除了‘\0’之外的字符数,所有申请动态内存时应该用strlen(s)+1。下面给出
此函数的实现:
char *strdup(char *s) { char *p; p = (char *)malloc(strlen(s)+1); if(p != 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); } }
大家应该注意到了,我们还有getword、getch、ungetch函数为实现,下面将对其一一解释:
第一个:getch函数和ungetch函数
顾名思义,这两个的作用一个是获取字符,一个是压回字符,其实这是堆栈的结构,我们需要
一个足够大的数组来实现静态数组的堆栈:
#define BUFSIZE 100//缓冲区的大小
char buf[BUFSIZE];//字符缓冲区
int bufp = 0;//缓冲区中的下一个位置
下面给出这两个函数的实现:
int getch(void) { return (bufp > 0) ? buf[--bufp] : getchar(); } void ungetch(int c) { if(bufp >= BUFSIZE) printf("ungetch: too many characters\n"); else buf[bufp++] = c; }
最后,我们来看一看getword函数,这个函数将从缓冲区中获取一个字符,这个字符开头必须是字母,
它返回的字符是输入字符串的第一个字符,代码如下:
int getword(char *word,int lim) { int c; char *w = word; while(isspace(c = getch())) ; if(c != EOF) *w++ = c; if(!isalpha(c)) { *w = '\0'; return c; } for(;--lim > 0;w++) { if(!isalnum(*w = getch())) { ungetch(*w); break; } } *w = '\0'; return word[0]; }
这样我们就可以轻易的实现的文本中的单词统计了。
附录(完整代码):
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp = 0;
struct tnode
{
char *word;
int count;
struct tnode *left;
struct tnode *right;
};
int getch(void);
void ungetch(int c);
int getword(char *word,int lim);
struct tnode *addTree(struct tnode *p,char *w);
struct tnode *talloc(void);
char *strdup(char *s);
void treePrint(struct tnode *p);
main()
{
struct tnode *root;
char word[100];
root = NULL;
while(getword(word,100) != EOF)
if(isalpha(word[0]))
root = addTree(root,word);
treePrint(root);
system("pause");
return 0;
}
int getword(char *word,int lim) { int c; char *w = word; while(isspace(c = getch())) ; if(c != EOF) *w++ = c; if(!isalpha(c)) { *w = '\0'; return c; } for(;--lim > 0;w++) { if(!isalnum(*w = getch())) { ungetch(*w); break; } } *w = '\0'; return word[0]; }
struct tnode *addTree(struct tnode *p,char *w) { int cond; if(p == NULL) { p = talloc(); p->word = strdup(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 = addTree(p->left,w); else p->right = addTree(p->right,w); return p; }
struct tnode *talloc(void)
{
return (struct tnode *)malloc(sizeof(struct tnode));
}
char *strdup(char *s) { char *p; p = (char *)malloc(strlen(s)+1); if(p != 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); } }
int getch(void) { return (bufp > 0) ? buf[--bufp] : getchar(); } void ungetch(int c) { if(bufp >= BUFSIZE) printf("ungetch: too many characters\n"); else buf[bufp++] = c; }
相关文章推荐
- 利用Map实现的统计每个输入字符串或则单词出现的次数
- c++实现文本中英文单词和汉字字符的统计
- 统计输入中所有单词出现的次数(使用二叉查找树实现:递归和非递归)
- 利用python内置函数,快速统计单词在文本中出现的次数
- Python实现统计文本当中单词的数量,
- 题目及解答:通过命令行输入多个单词,统计单词次数(利用新特性)
- go语言之map练习(二):编写一个程序wordfreq程序,统计输入文本中每个单词出现的频率(次数)
- 利用C语言实现:输入两个字符串,统计一个字符串在另一个字符串中出现的次数 。
- C语言实现二叉树-利用二叉树统计单词数目
- 统计输入的行数、单词数与字符数用C实现
- 输入一段英文文本,用程序统计出现频率最高和最低的两个单词;
- 关于统计ascii码文本中英语单词的出现频率的c++实现
- 【编程珠玑】第十五章--字符串:统计文本中单词数量(C++的Map&C的结构体实现&POJ2418)
- 采用二叉搜索树来统计文本中单词出现的频率
- python实现统计文本中单词出现的频率
- 一个简单的程序,统计文本文档中的单词和汉字数,逆序排列(出现频率高的排在最前面)。python实现。
- c++实现文本中英文单词和汉字字符的统计
- 二叉树统计单词个数(二叉搜索树实现及模板)
- python实现文本中单词个数统计
- Java实现读取键盘输入保存到txt文件,再统计并输出每个单词出现次数的方法