Top K算法问题的实现

来源:互联网 发布:淘宝哪家铁观音正宗 编辑:程序博客网 时间:2024/06/09 17:15
  1. http://blog.csdn.net/v_july_v/article/details/6403777#comments
  2. //copyright@yansha &&July  
  3. //July、updated,2011.05.08  
  4.   
  5. //题目描述:  
  6. //搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的  
  7. //长度为1-255字节。假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果  
  8. //除去重复后,不超过3百万个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门),  
  9. //请你统计最热门的10个查询串,要求使用的内存不能超过1G。  
  10.   
  11. #include <iostream>  
  12. #include <string>  
  13. #include <assert.h>  
  14. using namespace std;  
  15.   
  16. #define HASHLEN 2807303  
  17. #define WORDLEN 30  
  18.   
  19. // 结点指针  
  20. typedef struct node_no_space *ptr_no_space;  
  21. typedef struct node_has_space *ptr_has_space;  
  22. ptr_no_space head[HASHLEN];  
  23.   
  24. struct node_no_space   
  25. {  
  26.     char *word;  
  27.     int count;  
  28.     ptr_no_space next;  
  29. };  
  30.   
  31. struct node_has_space  
  32. {  
  33.     char word[WORDLEN];  
  34.     int count;  
  35.     ptr_has_space next;  
  36. };  
  37.   
  38. // 最简单hash函数  
  39. int hash_function(char const *p)  
  40. {  
  41.     int value = 0;  
  42.     while (*p != '/0')  
  43.     {  
  44.         value = value * 31 + *p++;  
  45.         if (value > HASHLEN)  
  46.             value = value % HASHLEN;  
  47.     }  
  48.     return value;  
  49. }  
  50.   
  51. // 添加单词到hash表  
  52. void append_word(char const *str)  
  53. {  
  54.     int index = hash_function(str);  
  55.     ptr_no_space p = head[index];  
  56.     while (p != NULL)  
  57.     {  
  58.         if (strcmp(str, p->word) == 0)  
  59.         {  
  60.             (p->count)++;  
  61.             return;  
  62.         }  
  63.         p = p->next;  
  64.     }  
  65.       
  66.     // 新建一个结点  
  67.     ptr_no_space q = new node_no_space;  
  68.     q->count = 1;  
  69.     q->word = new char [strlen(str)+1];  
  70.     strcpy(q->word, str);  
  71.     q->next = head[index];  
  72.     head[index] = q;  
  73. }  
  74.   
  75.   
  76. // 将单词处理结果写入文件  
  77. void write_to_file()  
  78. {  
  79.     FILE *fp = fopen("result.txt""w");  
  80.     assert(fp);  
  81.       
  82.     int i = 0;  
  83.     while (i < HASHLEN)  
  84.     {  
  85.         for (ptr_no_space p = head[i]; p != NULL; p = p->next)  
  86.             fprintf(fp, "%s  %d/n", p->word, p->count);  
  87.         i++;  
  88.     }  
  89.     fclose(fp);  
  90. }  
  91.   
  92. // 从上往下筛选,保持小根堆  
  93. void sift_down(node_has_space heap[], int i, int len)  
  94. {  
  95.     int min_index = -1;  
  96.     int left = 2 * i;  
  97.     int right = 2 * i + 1;  
  98.       
  99.     if (left <= len && heap[left].count < heap[i].count)  
  100.         min_index = left;  
  101.     else  
  102.         min_index = i;  
  103.       
  104.     if (right <= len && heap[right].count < heap[min_index].count)  
  105.         min_index = right;  
  106.       
  107.     if (min_index != i)  
  108.     {  
  109.         // 交换结点元素  
  110.         swap(heap[i].count, heap[min_index].count);  
  111.           
  112.         char buffer[WORDLEN];  
  113.         strcpy(buffer, heap[i].word);  
  114.         strcpy(heap[i].word, heap[min_index].word);  
  115.         strcpy(heap[min_index].word, buffer);  
  116.           
  117.         sift_down(heap, min_index, len);  
  118.     }  
  119. }  
  120.   
  121. // 建立小根堆  
  122. void build_min_heap(node_has_space heap[], int len)  
  123. {  
  124.     if (heap == NULL)  
  125.         return;  
  126.       
  127.     int index = len / 2;  
  128.     for (int i = index; i >= 1; i--)  
  129.         sift_down(heap, i, len);  
  130. }  
  131.   
  132. // 去除字符串前后符号  
  133. void handle_symbol(char *str, int n)  
  134. {  
  135.     while (str[n] < '0' || (str[n] > '9' && str[n] < 'A') || (str[n] > 'Z' && str[n] < 'a') || str[n] > 'z')  
  136.     {  
  137.         str[n] = '/0';  
  138.         n--;  
  139.     }  
  140.       
  141.     while (str[0] < '0' || (str[0] > '9' && str[0] < 'A') || (str[0] > 'Z' && str[0] < 'a') || str[0] > 'z')  
  142.     {  
  143.         int i = 0;  
  144.         while (i < n)  
  145.         {  
  146.             str[i] = str[i+1];  
  147.             i++;  
  148.         }  
  149.         str[i] = '/0';  
  150.         n--;  
  151.     }  
  152. }  
  153.   
  154. int main()  
  155. {  
  156.     char str[WORDLEN];  
  157.     for (int i = 0; i < HASHLEN; i++)  
  158.         head[i] = NULL;  
  159.       
  160.     // 将字符串用hash函数转换成一个整数并统计出现频率  
  161.     FILE *fp_passage = fopen("string.txt""r");  
  162.     assert(fp_passage);  
  163.     while (fscanf(fp_passage, "%s", str) != EOF)  
  164.     {  
  165.         int n = strlen(str) - 1;  
  166.         if (n > 0)  
  167.             handle_symbol(str, n);  
  168.         append_word(str);  
  169.     }  
  170.     fclose(fp_passage);  
  171.       
  172.     // 将统计结果输入文件  
  173.     write_to_file();  
  174.       
  175.     int n = 10;  
  176.     ptr_has_space heap = new node_has_space [n+1];  
  177.       
  178.     int c;  
  179.       
  180.     FILE *fp_word = fopen("result.txt""r");  
  181.     assert(fp_word);  
  182.     for (int j = 1; j <= n; j++)  
  183.     {  
  184.         fscanf(fp_word, "%s %d", &str, &c);  
  185.         heap[j].count = c;  
  186.         strcpy(heap[j].word, str);  
  187.     }  
  188.       
  189.     // 建立小根堆  
  190.     build_min_heap(heap, n);  
  191.       
  192.     // 查找出现频率最大的10个单词  
  193.     while (fscanf(fp_word, "%s %d", &str, &c) != EOF)  
  194.     {  
  195.         if (c > heap[1].count)  
  196.         {  
  197.             heap[1].count = c;  
  198.             strcpy(heap[1].word, str);  
  199.             sift_down(heap, 1, n);  
  200.         }  
  201.     }  
  202.     fclose(fp_word);  
  203.       
  204.     // 输出出现频率最大的单词  
  205.     for (int k = 1; k <= n; k++)  
  206.         cout << heap[k].count << " " << heap[k].word << endl;  
  207.       
  208.     return 0;  
  209. }  
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 初中孩子沉迷动漫及画动漫画怎么办 打仗在派出所保释出来人跑了怎么办 贴门槛石瓷砖贴多了要怎么办 建设银行中职学生资助卡丢了怎么办 建行网银u盾丢了怎么办 深水区换气时喝了口水怎么办 撞到别人车了 我走了 怎么办 自己班同学被自己取好多外号怎么办 刚学会走路的宝宝脚外八字怎么办 宝宝两岁走路膝盖弯曲不直怎么办 一岁多的宝宝走路o型腿怎么办 21个月的宝宝走路o型腿怎么办 宝宝十一个月了0型腿怎么办 14个月宝宝o型腿怎么办 深蹲了三个月大腿变粗了怎么办 脚踢球时被踢肿了变紫了怎么办 没钱去健身房想要练出好身材怎么办 群里有人发反政府视频怎么办 部队取消番号后之前军人档案怎么办 新疆武警黄金部队新兵改革后怎么办 别人偷了自己的东西没有证据怎么办 家里项链被邻居偷了没有证据怎么办 知道是谁偷钱都是没有证据怎么办 武警驾照开地方车被交警拦了怎么办 双手擦了纤体瘦身膏辣疼怎么办 乳房全切术后切口裂开化脓怎么办 擦了锁水的霜之后出汗怎么办 用完瘦脸霜感觉脸部又痒又烧怎么办 嘴角起好多的小炮泡怎么办快好 DNF龙腾光环领错角色怎么办 海盗来了卡在新手奖励怎么办 海盗来了获得新手奖励卡了怎么办 魔域帐号忘了哪个区的了怎么办 魔域口袋版幻兽栏满了怎么办 苹果平板的密码和邮箱都忘了怎么办 二级报名忘了邮箱和密码怎么办 用身份证买的手机号变成空号怎么办 魔域口袋版背包幻兽满了怎么办? 魔域宝宝转世满了还不变雷怎么办 魔域口袋版家族试炼士气不足怎么办 聚水潭暂存位没有箱号怎么办?