欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

词频统计 求最大k个数

发布时间:2025/10/17 40 豆豆
生活随笔 收集整理的这篇文章主要介绍了 词频统计 求最大k个数 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

题外话:想当年,编译原理课偷懒没自己实现这玩意,欠的终究还是要还的,现在补回来了。。。

Write a program for displaying the ten most frequent words in a file

such that your program should be efficient in all complexity measures.

/*(针对大量数据的作法)
思路:每读一个单词 ,存入字典序的平衡二叉搜索树中,这样判断是否新单词或旧单词词频加一
的扫描时间复杂度大大减小;读取完整个文本,建好树后,遍历一遍树,用最小堆存取
词频最大的10个单词,堆顶为词频最小的单词,所以每次只要与堆顶比较,需要替换则重排,
遍历完即出结果
*/
/*
本来打算建一张10个数据结构大小的哈希表,存储10个出现频数最大的单词词频,逐个读短文单词
边插入树结点时边更新表,
之后想若同一单词出现的频数很多,这样同一个单词得更新表很多次,不划算,
不如建好等平衡树后
遍历一遍,找出count最大的十个单词,这样每个不同的单词只遍历一次。
*/
/*
以下程序strcpy虽然能正确执行,但实际上有问题,可以换为如下,我就不换了,就重写个strcpy函数就好
strncpy(path, src, sizeof(path) - 1);
path[sizeof(path) - 1] = '/0';
len = strlen(path);
*/

#include<stdio.h> #include<string> #include<string.h> #include<vector> #include<stdlib.h> using namespace std;#define wordLength 20 #define maxCountNum 10struct AVLTree {char word[wordLength];//单词int count;//计数int height;//树的深度struct AVLTree* lTree;//左子树struct AVLTree* rTree;//右子树 };/*存储出现频率最大的十个结点*/ struct MAXCount {//string word;char word[wordLength];//单词int count;//计数 }; vector <struct MAXCount> maxCount(maxCountNum);/*返回大值*/ int Max(int a,int b); /*返回结点的深度*/ int Height(struct AVLTree* node); /*插入子结点*/ struct AVLTree* insertNode(char *word,struct AVLTree* root); /*删除树所有结点*/ void deleteTree(struct AVLTree** root); /*遍历显示树*/ void display(struct AVLTree* root); /*右旋转*/ struct AVLTree* LLRotate(struct AVLTree* root); /*左旋转*/ struct AVLTree* RRRotate(struct AVLTree* root); /*先左后右旋转*/ struct AVLTree* LRRotate(struct AVLTree* root); /*先右后左旋转*/ struct AVLTree* RLRotate(struct AVLTree* root); /*判断是否是出现频率最多的10个单词 与堆顶最小值比较 是:替换,重排*/ void maxCountWord(struct AVLTree* root); /*去除单词尾的标点符号 并把首字母为大写的转换为小写*/ void punctuationRid_LetterChange(char *temp); /*堆排序 最小堆*/ void heapSort(vector<struct MAXCount> &maxCount, int root, int end); /*结果显示 词频最大的十个单词*/ void showMaxCountWord(); /*返回大值*/ int Max(int a,int b) {return a>b?a:b; }/*返回结点的深度*/ int Height(struct AVLTree* node) {if(node == NULL)return -1;return node->height; }/*按字典序比较strcmp() str1>str2 返回正数str1=str2 返回零str1<str2 返回负数 *//*插入子结点*/ struct AVLTree* insertNode(char *word,struct AVLTree* root) {if(root == NULL){root=(struct AVLTree*)malloc(sizeof(struct AVLTree));strcpy(root->word,word);root->count=1;root->height=0;root->lTree=NULL;root->rTree=NULL;}else if(strcmp(word,root->word) == 0){root->count++;}/*插入左子树*/else if(strcmp(word,root->word) < 0){root->lTree=insertNode(word,root->lTree);if (Height(root->lTree) - Height(root->rTree) == 2) /*AVL树不平衡*/{if (strcmp(word,root->lTree->word) < 0)//LL 右旋转{/*插入到了左子树左边, 做单旋转*/root = LLRotate(root);}else //LR 先左后右{/*插入到了左子树右边, 做双旋转*/root = LRRotate(root);}}}/*插入右子树*/else if(strcmp(word,root->word) > 0){root->rTree=insertNode(word,root->rTree);if (Height(root->rTree) - Height(root->lTree) == 2) /*AVL树不平衡*/{if (strcmp(word,root->rTree->word) > 0)//RR 左旋转{/*插入到了右子树右边, 做单旋转*/root = RRRotate(root);}else //RL 先右后左{/*插入到了右子树左边, 做双旋转*/root = RLRotate(root);}}}root->height=Max(Height(root->lTree),Height(root->rTree))+1;return root; }/*删除树所有结点*/ void deleteTree(struct AVLTree** root) {if(root == NULL || *root == NULL)return;deleteTree(&((*root)->lTree));deleteTree(&((*root)->rTree));free(*root);*root=NULL; }/*遍历显示树*/ void display(struct AVLTree* root) {if(root==NULL)return;static int cnt=0;display(root->lTree);//输出每个单词的词频//printf("[%2d]word:%20s\tcount:%d\r\n",cnt++,root->word,root->count);/*判断是否是出现频率最多的10个单词*/maxCountWord(root);display(root->rTree); }/*右旋转*/ struct AVLTree* LLRotate(struct AVLTree* root) {struct AVLTree* node;node=root->lTree;root->lTree=node->rTree;node->rTree=root;/*结点的位置变了, 要更新结点的高度值*/root->height=Max(Height(root->lTree),Height(root->rTree))+1;node->height=Max(Height(node->lTree),Height(node->rTree))+1;return node; }/*左旋转*/ struct AVLTree* RRRotate(struct AVLTree* root) {struct AVLTree* node;node = root->rTree;root->rTree = node->lTree;node->lTree = root;/*结点的位置变了, 要更新结点的高度值*/root->height=Max(Height(root->lTree),Height(root->rTree))+1;node->height=Max(Height(node->lTree),Height(node->rTree))+1;return node; }/*先左后右旋转*/ struct AVLTree* LRRotate(struct AVLTree* root) {root->lTree=RRRotate(root->lTree);return LLRotate(root); }/*先右后左旋转*/ struct AVLTree* RLRotate(struct AVLTree* root) {root->rTree=LLRotate(root->rTree);return RRRotate(root); }/*判断是否是出现频率最多的10个单词 与堆顶最小值比较 是:替换,重排*/ void maxCountWord(struct AVLTree* root) {if(root->count>maxCount[0].count){//替换strcpy(maxCount[0].word,root->word);maxCount[0].count=root->count;heapSort(maxCount,0,10);} }/*去除单词尾的标点符号 并把首字母为大写的转换为小写*/ void punctuationRid_LetterChange(char *temp) {char *p=temp;if(*p >= 'A' && *p <= 'Z')*p=*p+32;while( *p != '\0')p++;//若最后一个字符不是字母 ,去除--p;if(*p >= 'a' && *p <= 'z');else*p='\0'; }/*堆排序 最小堆*/ void heapSort(vector<struct MAXCount> &maxCount, int root, int end) {for(int j=end-1;j>root;j--){int parent = (j-1-root)/2+root;//parent=(j-1)/2if(maxCount[parent].count > maxCount[j].count){//交换maxCount[parent].count += maxCount[j].count;maxCount[j].count = maxCount[parent].count - maxCount[j].count;maxCount[parent].count -= maxCount[j].count;char temp[20]="word_count";strcpy(temp,maxCount[parent].word);strcpy(maxCount[parent].word,maxCount[j].word);strcpy(maxCount[j].word,temp);}} }/*结果显示 词频最大的十个单词*/ void showMaxCountWord() {printf("------最大词频的十个单词如下-----\r\n");printf("word:\t\t\tcount:\r\n");for(int n=0;n<maxCountNum;n++){printf("%-20s\t%3d\r\n",maxCount[n].word,maxCount[n].count);}printf("------最大词频的十个单词如上-----\r\n"); }int main() {/*打开文件*/FILE *fp;if((fp=fopen("F:\\interview2\\Englishstory.txt","r")) == NULL){printf("File cannot be opened\n");exit(1);}else{/*初始化vector<struct MAXCount> maxCount(10) 建立最小堆*/ char *a="word_count";for(int n=0;n<10;n++){//maxCount[n].word[wordLength]=strcpy(maxCount[n].word,a);maxCount[n].count=0;}heapSort(maxCount,0,maxCountNum);//printf("File can be opened\n");char temp[wordLength];/*依据单词首字母依次转换为26棵树的根节点地址*/struct AVLTree *rootAddress=NULL;/*循环读取文本中的内容*/while((fscanf(fp,"%s",temp)) != EOF){//printf("temp:%s\r\n",temp);/*fscanf读出来的单词若是句尾,则会包含句尾的标点符号,punctuationRid_LetterChange函数 去掉尾的标点 转换头的大写*/punctuationRid_LetterChange(temp);//printf("temp:%s\r\n",temp);rootAddress=insertNode(temp,rootAddress);}display(rootAddress);showMaxCountWord();deleteTree(&rootAddress);/*关闭文件*/fclose(fp);}return 0; }

总结

以上是生活随笔为你收集整理的词频统计 求最大k个数的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。