集合(REDIS_SET)

第一個添加到集合的元素, 決定了創建集合時所使用的編碼:

  • 如果第一個元素可以表示爲 long long 類型值(也即是,它是一個整數, 接口isObjectRepresentableAsLongLong), 那麼集合的初始編碼爲 REDIS_ENCODING_INTSET 。
  • 否則,集合的初始編碼爲 REDIS_ENCODING_HT

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

  • intset 保存的整數值個數超過 server.set_max_intset_entries (默認值爲 512 )。
  • 試圖往集合裏添加一個新元素,並且這個元素不能被表示爲 long long 類型(也即是,它不是一個整數)。

1.  整數集合(REDIS_ENCODING_INTSET)的內存結構


2.  哈希集合的內存結構: 將字典的key作爲存儲數據的value;而將value置爲NULL.



1. 集合的交集算法:

示例:
redis 127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
redis 127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
redis 127.0.0.1:6379> sinter myset2 myset3
1) "two"

 1).  將所有需要計算交集的集合放到到一個集合數組中;
 2).  對數組進行排序,排序的數序是由各個集合的基數(即集合中成員個數)從小到大排序的,這樣排序是因爲後續查找比較過程中,從小的集合中找到相同的元素的概率比較小,如果找不到就中斷這個元素的查找;並且最小集合的元素較少,外面的循環的次數也最小,這樣效率比較高;
 3) 雙重循環進行比較查找: 從第一個集合中(最小元素個數)取各個元素和其他的集合中元素進行比較,如果在其他集合中都存在則記錄下來。

2. 集合的並集算法:
示例:
redis 127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
redis 127.0.0.1:6379> smembers myset3
1) "two" 
2) "one"
redis 127.0.0.1:6379> sunion myset2 myset3
1) "three"
2) "one"
3) "two"

   1).  將所有需要計算交集的集合放到到一個集合數組中;
   2).  雙重遍歷所有的集合,將元素添加的新的集合中,重複元素會添加失敗;


 3. 集合的差集算法:
示例:
redis 127.0.0.1:6379> smembers myset2
1) "three"
2) "two"
redis 127.0.0.1:6379> smembers myset3
1) "two"
2) "one"
redis 127.0.0.1:6379> sdiff myset2 myset3
1) "three"

   1).  將所有需要計算交集的集合放到到一個集合數組中;
   2). 差集的計算有兩種算法:
      a): 將數組中從sets[1]開始按基數從大到小排序(sets[0]位置不動), 這樣可以在後續計算中儘快找到重複元素, 遍歷sets[0]中的各個元素,如果某個元素在其他的集合中不存在, 則插入的新的差集集合(目的集合)中;算法的複雜度是O(N*M): N是sets[0]中元素的個數, M是集合的個數。
 
      b): 不對sets[]進行排序,將sets[0]中的所有元素都放到新的差集集合(目的集合)中;然後遍歷所有的剩餘的集合(從sets[1]開始)的元素,如果在目的集合中存在,則從目的集合中刪除該元素。算法的複雜度是O(N): N是所有集合元素的個數。

    兩種算法的選擇是由兩種算法的複雜度來比較選擇哪種算法,因爲第一種算法中只要找到一個集合中有不存在的查找的元素內循環就退出,因此對第一種算法的優先級進行提高(algo_one_work /= 2;),即對第一種進行除2提高。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章