前言:set類似于數(shù)學(xué)上面的集合概念,包含的元素?zé)o序,不能重復(fù),能進(jìn)行交、并、差操作。

      一、內(nèi)部原理

             set數(shù)據(jù)結(jié)構(gòu),也是隨著元素數(shù)目的多少而變化。當(dāng)set中添加的元素都是整數(shù)且元素數(shù)據(jù)較少時,set使用intset為底層的數(shù)據(jù)結(jié)構(gòu),否則,set使用dict作為底層的數(shù)據(jù)結(jié)構(gòu)。

             intset是什么?

             從字面意思可以看出是由整數(shù)組成的集合。是一個整數(shù)組成的有序集合,便于進(jìn)行二分查找,快速判斷一個元素是否屬于這個集合。內(nèi)存分配上也是一整塊連續(xù)的內(nèi)存空間,而且根據(jù)數(shù)值的大小采取了不同的編碼,對內(nèi)存使用進(jìn)行了優(yōu)化。
             intset數(shù)據(jù)結(jié)構(gòu)如下:

電腦培訓(xùn),計算機(jī)培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

 typedef struct intset {
    uint32_t encoding;/*數(shù)據(jù)編碼,表示intset中每個數(shù)據(jù)元素用幾個字節(jié)來存儲。有三種:數(shù)據(jù)編碼,表示intset中每個數(shù)據(jù)元素用幾個字節(jié)來存儲。
                       1.INTSET_ENC_INT16表示每個元素用2個字節(jié)存儲,
                       2.INTSET_ENC_INT32表示每個元素用4個字節(jié)存儲,
                       3.INTSET_ENC_INT64表示每個元素用8個字節(jié)存儲。
                       因此,intset中存儲的整數(shù)最多只能占用64bit*/
    uint32_t length; /*元素個數(shù)。encoding和length組成了intset頭部。*/    
    int8_t contents[]; /*是一個柔性數(shù)組,表示intset的header后面緊跟著數(shù)據(jù)元素。這個數(shù)組的總長度(即總字節(jié)數(shù))等于encoding * length*/     } intset;

電腦培訓(xùn),計算機(jī)培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

            注:intset可能會隨著數(shù)據(jù)的添加而改變它的數(shù)據(jù)編碼,創(chuàng)建時intset使用占內(nèi)存最小的INTSET_ENC_INT16作為編碼,每增加一個元素,則根據(jù)大小決定是否對數(shù)據(jù)編碼進(jìn)行改變。

            例子:

            電腦培訓(xùn),計算機(jī)培訓(xùn),平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),Web培訓(xùn),Web前端開發(fā)培訓(xùn)

             如上圖:
             1、新建一個intset只有一個header,總共8個字節(jié),encoding=2,length=0。
             2.、添加6,15之后,因為數(shù)值較小,所以encoding不變,length=2。
             3、添加32768的時候,超過了兩個字節(jié)(2個字節(jié)能表達(dá)的數(shù)據(jù)范圍是-32768~32767),此時encoding升級到INTSET_ENC_INT32為4,即用4個字節(jié)表示一個元素。 
             4、添加元素都是按照從小到大的順序。
             5、intset是按little endian模式存儲的。在上圖intset添加完所有數(shù)據(jù)之后,32768=>0x00008000
             什么時間轉(zhuǎn)為dict?
             1、大于512,默認(rèn)設(shè)置:set-max-intset-entries 512
             2、超出最大范圍-264~264-1
             3、元素里面包含非數(shù)字
             set底層用dict時,key是要添加的元素,value為NULL。
             區(qū)別:
             小集合(整數(shù))用intset存儲節(jié)省內(nèi)存。dict帶來的開銷很大(包含元數(shù)據(jù)信息,兩個hash表、鏈表指針等等)
             從時間復(fù)雜度上看,intset是o(log n),而dict可以認(rèn)為是o(1)(因為zipmap),但是intset元素個數(shù)較少,影響不大

      二、相關(guān)操作
             SADD key member [member ...] 
             將一個或多個元素加入到集合key中,已存在被忽略。若不存在,則創(chuàng)建。
             SCARD key
             返回集合key的數(shù)目。
             SDIFF key [key ...]
             返回集合之間的差集
             SDIFFSTORE destination key [key ...]
             返回集合之間的差集,并將結(jié)果存儲到目標(biāo)集合。
             SINTER key [key ...]
             返回集合集合之間的交集
             SINTERSTORE destination key [key ...] 
             返回集合之間的交集,并將結(jié)果存儲到目標(biāo)集合。
             SISMEMBER key member
             判斷元素是否屬于集合key的成員。
             SMOVE source destination member
             將元素從源集合移動到目標(biāo)集合。
             SPOP key
             隨機(jī)移除key集合的某一元素,并返回該元素。
             SRANDMEMBER key [count]
             隨機(jī)返回一個key集合的元素,若提供count參數(shù),則返回一個包含count個元素的數(shù)組。
             SREM key member [member ...]
             移除集合中的一個或多個元素。不存在則忽略。
             SUNION key [key ...]
             返回若干個集合的并集。
             SUNIONSTORE destination key [key ...]
             返回若干個集合的并集,并存儲在目標(biāo)集合

http://www.cnblogs.com/programlearning/p/7053396.html