倒排索引優化 - 跳表求交集 空間換時間 貪心


from:http://www.cnblogs.com/jcli/p/3984809.html

如果待合並的兩個倒排表數據量很大, 但是交集很少時, 會是什么情況呢?
1
2
[ 1 , 2 , 3 , 4 , 5 , ... 10001 , 10005 ]
[ 1 , 10001 , 10008 ]

如果對這兩個做合並操作, 最后的交集結果只有  [1, 10001] 2個元素, 但是卻要做10001次移動和比較操作, 所以肯定有什么辦法來優化這一點. 可能你已經想到了, 我們做了這么多無用比較, 是因為我們每次指針向前移動的步子太小了點, 如果我們在每次比較后向前多移動一點, 可以忽略很比無用的操作. 這就是跳表的思想.

我們看第一個倒排表, 如果它以5000為步長前進, 進我們只需要向前查找兩個即可找到我們需要的元素: 10001 . 這里寫一個跳表功能的合並算法代碼:

a = range(10008)
b = [1, 10001, 10008]
 
i = j = 0
result = []
step = 100
count = 0
while i < len(a) and j < len(b):
    if a[i] == b[j]:
        result.append(a[i])
        i = i +1
        j = j + 1
        count = count + 1
    elif a[i] < b[j]:
        while (i + step < len(a)) and a[i+step] <= b[j]:
            i = i + step
            count = count + 1
        else:
            i = i + 1
            count = count + 1
    else:
        while (j + step < len(b)) and b[j+step] <= a[i]:
            j = j + 5000
            count = count + 1
        else:
            j = j + 1
            count = count + 1
 
print result
print count
上面代碼中故意構造了一個很大的集合 [0 ... 10007], 然后用變量count作為計數器來分析兩個算法分別執行的操作次數, 可以看到采用跳表算法時(我們模擬了step=100)的計算次數是207, 而用之前的方式計算次數是10008, 可見性能提升了很多倍.

這里有幾點說明下:

1. 這里為了簡單說明跳表的思路, 全部用了數組表示倒排表, 其實真實的數據結構應該是鏈表結構(linked list). 這才符合磁盤存儲結構. 

2. 跳表的原始結構算法比這個復雜, 而且根據場景的不同, 跳表有不同的實現. 這里因為不是利用跳表的快速查詢功能, 所以沒有多級指針索引概念, 詳細跳表實現查考: skip list 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM