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
