堆排序計算詞頻的topk真的比快排快嗎

2021-09-07 09:18:05 字數 1949 閱讀 7879

起初我一直以為計算topk問題堆排序效率會更加的高(實在是太蠢了),但是下面這段**輸出的時間差是相同的,這說明堆排序與快排在計算topk問題上所用的時間是相等的。

分析:對這個現象進行分析,首先快排的時間複雜度是o(n*log(n)),而對於堆排序分為兩個過程,第乙個過程是建堆過程,即下面**的get_topk()函式的第乙個迴圈,因為需要對從最後乙個不為葉子節點的節點(即索引n/2處)開始調整建堆,所以,時間複雜度為o(n/2*log(n));第二個過程為排序出前k,這部分的時間複雜度為o(k*log(n)),所以堆排序計算topk的時間複雜度為o(n/2*log(n))+o(k*log(n))=o(n*log(n))。其實跟快排是一樣的。

利弊,而在工程中我們通常需要頻繁計算某個文字的top-k此時,如果對於每個k都重新採用堆排序的第二個過程,時間複雜度會線性增加,還不如一次排序,以後就想要top多少就要top多少。但是所以nltk並沒有快排的這種方式求topk,

import math

import nltk

import jieba

import collections

import datetime

#start end 表示陣列heap的索引

def shift(start,end,heap):

per_head=start

left_child_index=2*start+1

max_index=left_child_index

while max_index<=end:

if max_indexmax_index+=1

if heap[per_head][1]temp=heap[max_index];

heap[max_index]=heap[per_head]

heap[per_head]=temp;

head=max_index

max_index=2*head+1

else:

break;

def get_topk(heap,k):

length=len(heap)

start=math.ceil(length/2)+1;

for i in range(0,start +1)[::-1]:

shift(i,length-1,heap)

for i in range(0,length)[::-1]:

temp=heap[i]

heap[i]=heap[0]

heap[0]=temp

if length-(i-1)==k:

break;

shift(0,i-1,heap)

return heap[-k:]

def nltk_topk(file_path,k):

raw=open(file_path).read()

text=nltk.text.text(jieba.lcut(raw))

fdist1=nltk.freqdist(text)

fre_dist_list=list(fdist1.items())

print(len(fre_dist_list))

m=sorted(fre_dist_list,key=lambda x:x[1])

return m[-k:]

def my_topk(file_path,k):

raw=open(file_path).read()

word_list=jieba.lcut(raw)

vocabulary=list(collections.counter(word_list).items())

return get_topk(vocabulary,k)

file_path='d:/test.txt';

my_start_time=datetime.datetime.now()

(my_topk(file_path,1))

堆排序的應用 TOPK問題

我們知道堆有大根堆和小根堆兩種,那麼在解決找堆中k個最大值的問題時應該用大根堆還是小根堆呢?答案是找k個最大的,要建立k大小的小堆。思路如下 比如下面這個陣列,要去取出其中最大的四個值,然後將後面的值與堆頂值比較,若大於堆頂值則彈出堆頂,將新的值加入堆 重複這個步驟,堆中的值會整體增大,陣列遍歷完後...

堆的應用 topK演算法和堆排序

1.topk找前 k 個最大的,建小堆,堆的大小為k 找前 k 個最小的,建大堆,堆的大小為k public class topktestdemo 2.遍歷陣列 for int i 0 i array.length i else 走到這裡,minheap中已經儲存了前k個最大的 列印 for int...

c 堆排序 以及堆排序比快排慢的原因

void heap build vector nums,int root,int length 某個節點為k,那麼他的父節點下標為 k 1 2,左右子節點下標為2k 1,2k 2 if nums root nums flag 把最大值放到root上 void heap sort vector num...