日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

关于某日访问次数最多的IP的topK问题的三种解法

發布時間:2023/11/28 生活经验 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于某日访问次数最多的IP的topK问题的三种解法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目描述

在july大神的博客中,看到這樣兩道題:

1. 海量日志數據,提取出某日訪問百度次數最多的那個IP。
2. 假設目前有一千萬個記錄(這些查詢串的重復度比較高,雖然總數是1千萬,但如果除去重復后,不超過3百萬個。一個查詢串的重復度越高,說明查詢它的用戶越多,也就是越熱門。),請你統計最熱門的10個查詢串,要求使用的內存不能超過1G。

現在我將兩題結合一下:

假如有1千萬+的ip,如何知道訪問次數最多的topk ip呢?假設k為10

來源:https://blog.csdn.net/v_JULY_v/article/details/6256463

生成1千萬的IP

我們來生成1千萬+的ip

# coding:utf-8
# /bin/pythondef generateRandom(rangeFrom, rangeTo):import randomreturn random.randint(rangeFrom,rangeTo)def generageMassiveIPAddr(fileLocation,numberOfLines):IP = []file_handler = open(fileLocation, 'a+')for i in range(numberOfLines):IP.append('10.197.' + str(generateRandom(0,255))+'.'+ str(generateRandom(0,255)) + '\n')file_handler.writelines(IP)file_handler.close()if __name__ == '__main__':from time import ctimeprint ctime()for i in range(10):print '  ' + str(i) + ": " + ctime()generageMassiveIPAddr('imassiveIP.txt', 1000000)print ctime()

通過這段代碼我們可以在當前的目錄生成一個10010000行的imassiveIP.txt文件

$ wc -l imassiveIP.txt 
10010000 imassiveIP.txt

我將這個文件作為我們的數據來進行實驗

解法1 通過linux shell來計算,實現最快

$ time cat imassiveIP.txt | sort | uniq -c | sort -nrk1 | head -n 10204 10.197.30.171202 10.197.92.207202 10.197.42.72201 10.197.195.77201 10.197.190.108200 10.197.49.128200 10.197.236.54200 10.197.223.59200 10.197.145.27199 10.197.43.98real    1m18.731s
user    1m17.010s
sys     0m1.090s

可以看到我們花費時間為1m18.731s
綜合分析一下,第一步排序的時間復雜度是O(NlgN),而uniq遍歷的時間復雜度是O(N),假設去重后的數為M個,則第二步排序的時間復雜度為O(MlgM)因此該算法的總體時間復雜度就是O(N+NlgN+MlgM)=O(NlgN)

解法2 Hash Table法+部分排序

  • 第一步:維護一個Key為IP字串,Value為該IP出現次數的HashTable,每次讀取一個IP,如果該字串不在Table中,那么加入該字串,并且將Value值設為1;如果該字串在Table中,那么將該字串的計數加一即可。最終我們在O(N)的時間復雜度內完成了對該海量數據的處理。
    • 第二步 題目要求是求出Top 10,因此我們沒有必要對所有的IP都進行排序,我們只需要維護一個10個大小的數組,初始化放入10個IP,按照每個IP的統計次數由大到小排序,排序的時間復雜度為O(klg(k)), 假設去重后的數為M個, 然后遍歷這M條記錄,每讀一條記錄就和數組最后一個IP對比,如果小于這個IP,那么繼續遍歷,否則,將數組中最后一條數據淘汰,加入當前的IP。最后當所有的數據都遍歷完畢之后,那么這個數組中的10個IP便是我們要找的Top10了。

python 代碼實現

#coding:utf-8
#/bin/pythonimport sys, os
from collections import defaultdictdef main():if len(sys.argv) != 2:print "Usage: python **.py topK"sys.exit(1)else:#print sys.argvk = int(sys.argv[1])res_dict = defaultdict(int)topk_dict = defaultdict(int)for line in sys.stdin:res_dict[line.strip()] += 1topk_dict_sorted = []for key, value in res_dict.items():if len(topk_dict) <= k:topk_dict[key] = valueif len(topk_dict) == k:topk_dict_sorted = sorted(topk_dict.items(), key=lambda x:x[1], reverse=True)else:if topk_dict_sorted[-1][1] < value:topk_dict_sorted.pop()topk_dict_sorted.append((key, value))topk_dict_sorted = sorted(topk_dict_sorted, key=lambda x:x[1], reverse=True)if len(topk_dict_sorted) < k:topk_dict_sorted = sorted(topk_dict.items(), key=lambda x:x[1], reverse=True)for key, value in topk_dict_sorted:print "%s\t%d"%(key, value)if __name__ == '__main__':main()

結果如下

$ time cat imassiveIP.txt| python get_top10.py 10             
10.197.30.171   204
10.197.92.207   202
10.197.42.72    202
10.197.190.108  201
10.197.195.77   201
10.197.236.54   200
10.197.145.27   200
10.197.49.128   200
10.197.223.59   200
10.197.241.183  199real    0m5.046s
user    0m4.730s
sys     0m0.290s

我們發現我們只需要用5.046s就可以找到這個top10的ip

綜合分析一下,第一步統計頻數時間復雜度是O(N),假設去重后的數為M個,則第二步計算的時間復雜度為O(M*k*lgk), 其中O(k*lgk)為對k個數排序的時間復雜度,因此該算法的總體時間復雜度就是O(N+M*k*lgk),這個速度比直接shell已經快了10幾倍了。

方法3 Hash Table法+堆

我們主要做的優化是如何在去重后的M個IP中找到topK個最大的,在方法二中,我們采取的是先排序然后插入到最后位置排序, 其實也可以通過采用二分的方法查找,應該插入的合適位置,這樣就可以避免再排序,這樣操作的復雜度就降到了logK,可是,隨之而來的問題就是數據移動,因為移動數據次數增多了。有沒有既能快速查找,又能快速移動元素的數據結構呢?回答是肯定的,那就是
借助堆結構,我們可以在log量級的時間內查找和調整/移動。因此到這里,我們的算法可以改進為這樣,維護一個K(該題目中是10)大小的小根堆,然后遍歷M個IP,分別將出現次數和根元素進行對比。
具體過程是:
堆頂存放的是整個堆中最小的數,現在遍歷N個數,把最先遍歷到的k個數存放到最小堆中,并假設它們就是我們要找的最大的k個數,X1>X2...XminX1>X2...Xmin(堆頂),而后遍歷后續的N-K個數,一一與堆頂元素進行比較,如果遍歷到的XiXi大于堆頂元素XminXmin,則把Xi放入堆中,而后更新整個堆,更新的時間復雜度為O(lgK),如果Xi<XminXi<Xmin則不更新堆,整個過程的復雜度為O(K)+O((M-K)*logK)=O(M*logK)

這個有個關于堆排序很好3d動畫鏈接

python 實現1

一個速度還可以但是空間復雜度很高的程序,在python中有個heapq可以直接實現堆.關于heap的詳細用法可以看這里
我們把所有的數據都都放在堆中,然后直接返回最大的k個數據就可以了,時間復雜度是Time complexity: O(M + klogM),總的時間復雜度為O(N+M+klgM)

#coding:utf-8
#/bin/pythonimport sys, os
from collections import defaultdict
import heapqdef main():if len(sys.argv) != 2:print "Usage: python **.py topK"sys.exit(1)else:#print sys.argvk = int(sys.argv[1])res_dict = defaultdict(int)heap_res = []for line in sys.stdin:res_dict[line.strip()] += 1for key, value in res_dict.items():heap_res.append((value, key))heap_res = heapq.nlargest(k, heap_res)for key, value in heap_res:print "%s\t%d"%(value, key)if __name__ == '__main__':main()

結果如下:

$ time cat imassiveIP.txt | python get_top10_heap.py 10                   
10.197.30.171   204
10.197.92.207   202
10.197.42.72    202
10.197.195.77   201
10.197.190.108  201
10.197.49.128   200
10.197.236.54   200
10.197.223.59   200
10.197.145.27   200
10.197.43.98    199real    0m5.085s
user    0m4.760s
sys     0m0.300s

python實現2

如果不排序輸出 Time Complexity: O(k + (M-k)Logk),如果排序輸出Time Complexity:O(k + (M-k)Logk + kLogk)=O(k + MLogk),所以總的Time Complexity:O(N + k + MLogk)

#coding:utf-8
#/bin/pythonimport sys, os
from collections import defaultdict
import heapqdef main():if len(sys.argv) != 2:print "Usage: python **.py topK"sys.exit(1)else:k = int(sys.argv[1])res_dict = defaultdict(int)heap_res = []for line in sys.stdin:res_dict[line.strip()] += 1for key, value in res_dict.items():if len(heap_res) < k:heap_res.append((value, key))if len(heap_res) == k:heapq.heapify(heap_res)else:if value > heap_res[0][0]:heapq.heappushpop(heap_res, (value, key))heap_res = heapq.nlargest(k, heap_res)for key, value in heap_res:print "%s\t%d"%(value, key)if __name__ == '__main__':main()

結果如下:

$ time cat imassiveIP.txt | python get_top10_heap.py 10    
10.197.30.171   204
10.197.92.207   202
10.197.42.72    202
10.197.195.77   201
10.197.190.108  201
10.197.49.128   200
10.197.236.54   200
10.197.223.59   200
10.197.145.27   200
10.197.43.98    199real    0m4.917s
user    0m4.670s
sys     0m0.220s

總結

如果我們處理大批量的數據時候,還是要學會優化代碼,但是掌握shell的命令行使用方法,可以極大的提高我們的效率

參考鏈接

十一、從頭到尾解析Hash表算法
【原創】Python處理海量數據的實戰研究
https://www.geeksforgeeks.org/k-largestor-smallest-elements-in-an-array/

總結

以上是生活随笔為你收集整理的关于某日访问次数最多的IP的topK问题的三种解法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 精品99久久久久成人网站免费 | 性生交大全免费看 | 国产精品区一区二区三 | 999精品在线视频 | 成年人黄色片 | 天天色综合影视 | 日韩人妻精品在线 | 国产精品麻豆成人av电影艾秋 | 亚洲a在线观看 | 国产精品视频在线观看 | 天天天干| 日本天堂一区 | 免费的污网站 | 一起草国产 | 中文字幕有码av | 久久久久久成人精品 | 日本一区二区三区四区视频 | 久久人体 | 五月天综合社区 | 国产精品美女久久久久av爽 | 欧美做受喷浆在线观看 | av撸撸在线| 久精品在线| 影音先锋中文字幕在线视频 | 韩国色网 | 亚洲国产麻豆 | 亚洲91色 | 激情五月色综合国产精品 | 国产一国产精品一级毛片 | 亚洲综合另类小说 | 69精品丰满人妻无码视频a片 | 日韩欧美一级在线 | 一级国产黄色片 | 中文字幕丰满乱子伦无码专区 | www.桃色av嫩草.com | 一色桃子juy758在线播放 | 久久久久久免费观看 | 精品国产精品国产偷麻豆 | 国产免费福利视频 | 欧美性生活一级 | 伊人操 | 国产成人一区二区 | 免费观看日批视频 | 国产jizz| 夜色福利 | 337p日本欧洲亚洲大胆精筑 | 伊人免费视频 | 亚洲六月丁香色婷婷综合久久 | 国产一区中文 | 深夜影院深a | 91禁外国网站 | 手机av在线不卡 | 在线精品一区二区 | 欧美日韩一区二区三区在线观看 | 亚欧洲精品 | 日本三级视频在线 | 成年人免费看黄色 | 久久一道本 | 国产精品视频久久久久久久 | 男生女生操操操 | 好吊操精品视频 | 黑人巨大精品欧美黑寡妇 | 色婷婷久久久 | 亚洲日本在线观看 | 精品在线视频免费观看 | 午夜黄色影院 | 亚洲自拍偷拍色图 | 搡国产老太xxx网站 高h喷汁呻吟3p | jizz欧美大全 | 成人在线视频一区 | 欧美区一区二区 | 国产白嫩美女无套久久 | 中文字幕无码毛片免费看 | 久久久久久9999 | 国产精品人人做人人爽 | 麻豆天天躁天天揉揉av | av毛片观看 | 456亚洲影院| www.日本黄色 | 国产1区2区3区4区 | 青青草社区视频 | 性高跟鞋xxxxhd人妖 | 国产视频一区二区在线 | 18xxxx日本 | 海角社区id | 99久在线精品99re8热 | 一级特黄aa大片欧美 | 成年人毛片 | 老头av| 亚州黄色网址 | 国产在线观看精品 | 久久亚洲私人国产精品va | 国产视频综合在线 | 国产人妖在线 | 久久天天综合 | 亚洲欲色 | 在线观看欧美日韩视频 | 少妇人妻互换不带套 | 黄a大片 |