1. 程式人生 > >統計出現次數最多的資料

統計出現次數最多的資料

題目描述:
給你上千萬或上億資料(有重複),統計其中出現次數最多的前N個數據。

    分析:上千萬或上億的資料,現在的機器的記憶體應該能存下(也許可以,也許不可以)。所以考慮採用hash_map/搜尋二叉樹/紅黑樹等來進行統計次數。然後就是取出前N個出現次數最多的資料了。當然,也可以堆實現。

    ok,此題與上題類似,最好的方法是用hash_map統計出現的次數,然後再借用堆找出出現次數最多的N個數據。不過,上一題統計搜尋引擎最熱門的查詢已經採用過hash表統計單詞出現的次數,特此,本題咱們改用紅黑樹取代之前的用hash表,來完成最初的統計,然後用堆更新,找出出現次數最多的前N個數據。

    同時,正好個人此前用c && c++ 語言實現過紅黑樹,那麼,程式碼能借用就借用吧。
完整程式碼

  1. //[email protected] zhouzhenren &&July
  2. //July、updated,2011.05.08.
  3. //題目描述:
  4. //上千萬或上億資料(有重複),統計其中出現次數最多的前N個數據
  5. //解決方案:
  6. //1、採用紅黑樹(本程式中有關紅黑樹的實現程式碼來源於@July)來進行統計次數。
  7. //2、然後遍歷整棵樹,同時採用最小堆更新前N個出現次數最多的資料。
  8. //宣告:版權所有,引用必須註明出處。
  9. #define PARENT(i) (i)/2
  10. #define LEFT(i)   2*(i)
  11. #define RIGHT(i)  2*(i)+1
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. typedefenum rb_color{ RED, BLACK }RB_COLOR;  
  16. typedefstruct rb_node  
  17. {  
  18.     int key;  
  19.     int data;  
  20.     RB_COLOR color;  
  21.     struct rb_node* left;  
  22.     struct
     rb_node* right;  
  23.     struct rb_node* parent;  
  24. }RB_NODE;  
  25. RB_NODE* RB_CreatNode(int key, int data)  
  26. {  
  27.     RB_NODE* node = (RB_NODE*)malloc(sizeof(RB_NODE));  
  28.     if (NULL == node)  
  29.     {  
  30.         printf("malloc error!");  
  31.         exit(-1);  
  32.     }  
  33.     node->key = key;  
  34.     node->data = data;  
  35.     node->color = RED;  
  36.     node->left = NULL;  
  37.     node->right = NULL;  
  38.     node->parent = NULL;  
  39.     return node;  
  40. }  
  41. /**  
  42. * 左旋   
  43. * 
  44. *  node           right  
  45. *  / /    ==>     / /  
  46. * a  right     node  y  
  47. *     / /       / /      
  48. *     b  y     a   b     
  49. */
  50. RB_NODE* RB_RotateLeft(RB_NODE* node, RB_NODE* root)  
  51. {    
  52.     RB_NODE* right = node->right;    // 指定指標指向 right<--node->right  
  53.     if ((node->right = right->left))      
  54.         right->left->parent = node;  // 好比上面的註釋圖,node成為b的父母
  55.     right->left = node;   // node成為right的左孩子 
  56.     if ((right->parent = node->parent))    
  57.     {    
  58.         if (node == node->parent->right)    
  59.             node->parent->right = right;  
  60.         else
  61.             node->parent->left = right;  
  62.     }    
  63.     else
  64.         root = right;    
  65.     node->parent = right;  //right成為node的父母  
  66.     return root;    
  67. }    
  68. /** 
  69. * 右旋   
  70. * 
  71. *      node            left  
  72. *       / /             / /  
  73. *     left y   ==>     a  node  
  74. *     / /                  / /  
  75. *    a   b                b   y   
  76. */
  77. RB_NODE* RB_RotateRight(RB_NODE* node, RB_NODE* root)    
  78. {    
  79.     RB_NODE* left = node->left;    
  80.     if ((node->left = left->right))    
  81.         left->right->parent = node;    
  82.     left->right = node;    
  83.     if ((left->parent = node->parent))    
  84.     {    
  85.         if (node == node->parent->right)      
  86.             node->parent->right = left;    
  87.         else
  88.             node->parent->left = left;    
  89.     }    
  90.     else
  91.         root = left;    
  92.     node->parent = left;    
  93.     return root;    
  94. }    
  95. /**  
  96. * 紅黑樹的3種插入情況   
  97. * 用z表示當前結點, p[z]表示父母、p[p[z]]表示祖父, y表示叔叔. 
  98. */
  99. RB_NODE* RB_Insert_Rebalance(RB_NODE* node, RB_NODE* root)    
  100. {    
  101.     RB_NODE *parent, *gparent, *uncle, *tmp;  //父母p[z]、祖父p[p[z]]、叔叔y、臨時結點*tmp  
  102.     while ((parent = node->parent) && parent->color == RED)    
  103.     { // parent 為node的父母,且當父母的顏色為紅時  
  104.         gparent = parent->parent;   // gparent為祖父  
  105.         if (parent == gparent->left)  // 當祖父的左孩子即為父母時,其實上述幾行語句,無非就是理順孩子、父母、祖父的關係。
  106.         {  
  107.             uncle = gparent->right; // 定義叔叔的概念,叔叔y就是父母的右孩子。  
  108.             if (uncle && uncle->color == RED) // 情況1:z的叔叔y是紅色的  
  109.             {    
  110.                 uncle->color = BLACK;   // 將叔叔結點y著為黑色  
  111.                 parent->color = BLACK;  // z的父母p[z]也著為黑色。解決z,p[z]都是紅色的問題。  
  112.                 gparent->color = RED;      
  113.                 node = gparent;     // 將祖父當做新增結點z,指標z上移倆層,且著為紅色。  
  114.                 // 上述情況1中,只考慮了z作為父母的右孩子的情況。  
  115.             }    
  116.             else// 情況2:z的叔叔y是黑色的,  
  117.             {       
  118.                 if (parent->right == node)  // 且z為右孩子  
  119.                 {    
  120.                     root = RB_RotateLeft(parent, root); // 左旋[結點z,與父母結點]  
  121.                     tmp = parent;    
  122.                     parent = node;    
  123.                     node = tmp;     // parent與node 互換角色  
  124.                 }    
  125.                 // 情況3:z的叔叔y是黑色的,此時z成為了左孩子。  
  126.                 // 注意,1:情況3是由上述情況2變化而來的。  
  127.                 // ......2:z的叔叔總是黑色的,否則就是情況1了。  
  128.                 parent->color = BLACK;   // z的父母p[z]著為黑色  
  129.                 gparent->color = RED;    // 原祖父結點著為紅色  
  130.                 root = RB_RotateRight(gparent, root); // 右旋[結點z,與祖父結點]  
  131.             }    
  132.         }     
  133.         else
  134.         {         
  135.             // 這部分是特別為情況1中,z作為左孩子情況,而寫的。  
  136.             uncle = gparent->left;  // 祖父的左孩子作為叔叔結點。[原理還是與上部分一樣的]  
  137.             if (uncle && uncle->color == RED)  // 情況1:z的叔叔y是紅色的  
  138.             {    
  139.                 uncle->color = BLACK;    
  140.                 parent->color = BLACK;    
  141.                 gparent->color = RED;    
  142.                 node = gparent;           // 同上
  143.             }    
  144.             else// 情況2:z的叔叔y是黑色的,  
  145.             {    
  146.                 if (parent->left == node)  // 且z為左孩子  
  147.                 {    
  148.                     root = RB_RotateRight(parent, root);  // 以結點parent、root右旋  
  149.                     tmp = parent;    
  150.                     parent = node;    
  151.                     node = tmp;       // parent與node 互換角色  
  152.                 }     
  153.                 // 經過情況2的變化,成為了情況3.  
  154.                 parent->color = BLACK;    
  155.                 gparent->color = RED;    
  156.                 root = RB_RotateLeft(gparent, root);   // 以結點gparent和root左旋  
  157.             }    
  158.         }    
  159.     }    
  160.     root->color = BLACK; // 根結點,不論怎樣,都得置為黑色。  
  161. 相關推薦

    統計出現次數資料

    題目描述: 給你上千萬或上億資料(有重複),統計其中出現次數最多的前N個數據。     分析:上千萬或上億的資料,現在的機器的記憶體應該能存下(也許可以,也許不可以)。所以考慮採用hash_map/搜尋二叉樹/紅黑樹等來進行統計次數。然後就是取出前N個出現

    Linux下統計出現次數的指定欄位值

    假設桌面上有一個data.txt文字,內容如下: {id='xxx' info='xxx' kk='xxx' target='111111' dd='xxx'} {id='xxx' info='xxx' kk='xxx' target='777' dd='xxx'} {i

    用hash_map統計出現次數的前N個URL

    海量資料統計頻率最高詞彙的常規辦法之一是先通過一個hash函式處理資料然後取模N,拆分為N個小檔案,對每一個小檔案進行詞頻統計和排序處理,然後歸併N個小檔案取頻率最大的M個數。 關於hash_map和map的選擇使用有幾點注意的,hash_map是hash表的形式實

    Js面試題(二)--js實現統計出現次數字符個數

    round rip ont js面試 () jos 圖片 第一個字符 clas 話不多話,直接上圖 統計出現次數最多的字符是哪個? 1、當然首先想到的是循環這個字符···· 2、用for循環--第一次檢索到

    上千萬或上億資料(有重複),統計其中出現次數的N個數據. C++實現

    上千萬或上億的資料,現在的機器的記憶體應該能存下。所以考慮採用hash_map/搜尋二叉樹/紅黑樹等來進行統計次數。然後就是取出前N個出現次數最多的資料了,可以用第2題提到的堆機制完成。 #in

    判斷一個字符串中出現次數的字符,統計這個次數

    sdff BE 出現次數 div asd 遍歷 轉換成 arr str var str = ‘abaasdffggghhjjkkgfddsssss3444343‘; // 1.將字符串轉換成數組 var newArr = str.spl

    返回(統計)一個列表中出現次數的元素

    clas 列表 元素 center enter ax1 叠代器 orm {} 首先定義一個函數 函數內逐行依次解釋為: #定義一個函數def max1(lt):   dict1 = {} #建立一個空字典 s = set(lt)

    判斷一個字符串中出現次數的字符,並統計字數

    spa bbbb aci light turn border java UNC ber \1 等於 (\w) var s = ‘aaabbbcccaaabbbaaabbbbbbbbbb‘; var a = s.split(‘‘); a.sort();

    (ES6的“...“配合ES5‘’forEach‘’)前端面試之判斷一個字串中出現次數的字元,統計這個次數

    // 判斷一個字串中出現次數最多的字元,統計這個次數 let str = 'aasdadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddsdasjjhsghkafsagjkg

    演算法--統計文字中出現次數的單詞(字典樹)

    統計一個文字中,出現次數最多的單詞:單詞全部小寫,單詞與單詞之間以空格間隔 1.利用字典  key為單詞  value為單詞出現的次數 def mostString(): dict = {} fr = open('preprocessing.txt')

    sort +awk+uniq 統計檔案中出現次數的前10個單詞

    原文地址:http://blog.sina.com.cn/s/blog_5dce657a01012ddi.html   作者:小新 例項cat logt.log|sort -s -t '-' -k1n |awk '{print $1;}'|uniq -c|sort -k1nr|head

    如何統計一本英文書(比如簡愛)中出現次數的前1000個單詞

    如何統計一本書中出現最多的前1000個單詞,其實只要處理好新單詞的儲存,已經出現單詞個數的統計,和根據出現次數的排序,就基本完成了這個專案。 思路:1、從檔案中依次讀取一個個字元,如果是字母字元就放到一個字元陣列中,當讀取的字元是空格或者標點符號時,則已經讀取的字串視為一個單詞,將其儲存起來。&

    js 判斷一個字串中出現次數的字元,統計出現次數

    js 判斷一個字串中出現次數最多的字元,統計其出現次數 var str = 'asdfssaaasasasasaa'; var json = {}; for (var i = 0; i < str.length; i++) { if(!json[str.charAt(i

    js統計陣列中出現次數的元素

    想來想去沒想出更好的解決方法。 思路就是在ana函式裡先遍歷一遍arr,維護一個數組newArr 用於將所有數值相同的放在陣列中的同一個塊內。另外一個數組unique 用於維護數值唯一,判斷當前的item是否已存在於newArr中。為了方便比較物件的數值相同,

    判斷一個字串中出現次數的字元,統計這個次數

    var str = 'asdfssaaasasasasaa'; var json = {}; for (var i = 0; i < str.length; i++) { if(!json[str.charAt(i)]){ json[str.cha

    linux中sort(統計檔案中出現次數的前10個單詞)

    例項 cat logt.log|sort -s -t '-' -k1n |awk '{print $1;}'|uniq -c|sort -k1nr|head -100 使用linux命令或者shell實現:檔案words存放英文單詞,格式為每行一個英文單詞

    numpy 統計陣列每一行出現次數的數字

    使用np.bincount()和np.argmax()函式來實現。 np.bincount()可以把陣列中出現的每個數字,當做index,數字出現的次數當做value來表示。 np.argmax()可以返回陣列中最大值的index。 所以經過變換,可以得到出現次數的最大值。

    統計陣列中出現次數的元素並輸出

    實驗過程中遇到一個實際問題:需要統計出10次計數的值中出現最多的一個數,比如輸入34 35 35 35 34 35 35 35 34 33 十個數,要求最終輸出35.如果出現兩個數同樣多,則輸出兩個元素中較小的那一個(也可以是較大的那一個,但是必須確定是其中一種)。 程式碼

    海量日誌資料,找出出現次數的IP地址。

    import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java

    Java統計一篇文章中出現次數的漢字或英文單詞 又出現次數統計

    思想是用到了Map集合的鍵唯一性儲存漢字或者單詞,單詞的獲取通過正則獲取: 統計類: import java.util.ArrayList; import java.util.Map; import java.util.Set; import java.util.Tree