Redis 資料型別之集合

2021-10-04 07:00:28 字數 3090 閱讀 7392

redis_set (集合)是 sadd 、 srandmember 等命令的操作物件, 它使用 redis_encoding_intset 和 redis_encoding_ht 兩種方式編碼。

編碼的選擇

第乙個新增到集合的元素, 決定了建立集合時所使用的編碼:

如果乙個集合使用 redis_encoding_intset 編碼, 那麼當以下任何乙個條件被滿足時, 這個集合會被轉換成 redis_encoding_ht 編碼: 集合

當使用 redis_encoding_ht 編碼時, 集合將元素儲存到字典的鍵裡面, 而字典的值則統一設為 null 。

redis 集合型別命令的實現, 主要是對 intset 和 dict 兩個資料結構的操作函式的包裝, 以及一些在兩種編碼之間進行轉換的函式, 大部分都沒有什麼需要解釋的地方, 唯一比較有趣的是 sinter 、 sunion 等命令之下的演算法實現, 以下三個小節就分別討論它們所使用的演算法。

求交集演算法

sinter 和 sinterstore 兩個命令所使用的求並交集演算法可以用 python 表示如下:

# coding: utf-8

defsinter

(*multi_set)

:# 根據集合的基數進行排序

sorted_multi_set =

sorted

(multi_set,

lambda x, y:

len(x)

-len

(y))

# 使用基數最小的集合作為基礎結果集,有助於降低常數項

result = sorted_multi_set[0]

.copy(

)# 剔除所有在 sorted_multi_set[0] 中存在

# 但在其他某個集合中不存在的元素

for elem in sorted_multi_set[0]

:for s in sorted_multi_set[1:

]:if(

not elem in s)

: result.remove(elem)

break

return result

演算法的複雜度為 o(n2) , 執行步數為 s∗t , 其中 s 為輸入集合中基數最小的集合, 而 t 則為輸入集合的數量。

求並集演算法

sunion 和 sunionstore 兩個命令所使用的求並集演算法可以用 python 表示如下:

# coding: utf-8

defsunion

(*multi_set)

: result =

set(

)for s in multi_set:

for elem in s:

# 重複的元素會被自動忽略

result.add(elem)

return result

演算法的複雜度為 o(n) 。

求差集演算法

redis 為 sdiff 和 sdiffstore 兩個命令準備了兩種求集合差的演算法。

以 python **表示的演算法一定義如下:

def

sdiff_1

(*multi_set)

: result = multi_set[0]

.copy(

) sorted_multi_set =

sorted

(multi_set[1:

],lambda x, y:

len(x)

-len

(y))

# 當 elem 存在於除 multi_set[0] 之外的集合時

# 將 elem 從 result 中刪除

for elem in multi_set[0]

:for s in sorted_multi_set:

if elem in s:

result.remove(elem)

break

return result

這個演算法的複雜度為 o(n2) , 執行步數為 s∗t , 其中 s 為輸入集合中基數最小的集合, 而 t 則為除第乙個集合之外, 其他集合的數量。

以 python **表示的演算法二定於如下:

# coding: utf-8

defsdiff_2

(*multi_set)

:# 用第乙個集合作為結果集的起始值

result = multi_set[0]

.copy(

)for s in multi_set[1:

]:for elem in s:

# 從結果集中刪去其他集合中包含的元素

if elem in result:

result.remove(elem)

return result

這個演算法的複雜度同樣為 o(n2) , 執行步數為 s , 其中 s 為所有集合的基數總和。

redis 使用乙個程式決定該使用那個求差集演算法, 程式用 python 表示如下:

# coding: utf-8

from sdiff_1 import sdiff_1

from sdiff_2 import sdiff_2

defsdiff

(*multi_set)

:# 演算法一的常數項較低,給它一點額外的優先順序

algo_one_advantage =

2 algo_one_weight =

len(multi_set[0]

)*len(multi_set[1:

])/ algo_one_advantage

algo_two_weight =

sum(

map(

len, multi_set)

)if algo_one_weight <= algo_two_weight:

return sdiff_1(

*multi_set)

else

:return sdiff_2(

*multi_set)

資料型別之集合

在python中集合分兩種 集合的特點 線性結構的查詢時間複雜度是o n 即隨著資料規模的增大而耗時增加。set和dict通過hash table實現,時間複雜度是o 1 查詢時間與資料規模無關。建立乙個set。注意 建立乙個空集合必須使用set 而不是 用來建立乙個空字典 s1 set abcde...

資料型別之集合

一 集合介紹 集合用於包含一組無序的物件。與列表和元組不同,集合是無序的,也無法通過數字進行索引。此外,集合中的元素不能重複。簡單總結 不重複,互異性 也就是說集合是天生去重的 元素為不可變物件,確定性,元素必須可hash 集合的元素沒有先後之分,無序性 二 集合的簡單操作 1.通過函式進行轉換 n...

資料型別之集合

集合 set 集合的元素是無序的,不重複的 1.獨有功能 1.增加元素 v v.add hh print v v.add hh print v d python3.6 python3.6.exe d python code day01 day06.py 2.刪除元素 v v.discard a pr...