redis資料結構之 intset
整數集合intset用於有序、無重複地儲存多個整數值,根據集合中元素的值自動選擇使用整數型別來儲存元素,例如:如果intset中絕對值最大的整數可以用int32_t來儲存,那麼整個intset中所有元素都使用int32_t來儲存。
如果當前intset所使用的型別不能儲存一個即將加入到該intset的新元素時候,需要對intset進行升級,比如新元素的型別是int64_t,而當前intset的型別是int32_t,那麼升級就是先將intset中所有元素由int32_t轉換為int64_t,然後再插入新元素。
對於int8_t,int32_t,int64_t我個人的理解就應該分別對應char,int,long long,使用int8_t,int32_t,int64_t應該是為了區分平臺的差異吧,具體的可以檢視stdint.h檔案。
整數集合的資料結構
?1 2 3 4 5 |
typedef
struct intset {
uint32_t
encoding; //所使用型別的長度,4\8\16
uint32_t
length; //元素個數
int8_t
contents[]; //儲存元素的陣列
}
intset;
|
encoding的值是下面三個常量中的一個:
#define INTSET_ENC_INT16 (sizeof(int16_t))
#define INTSET_ENC_INT32 (sizeof(int32_t))
#define INTSET_ENC_INT64 (sizeof(int64_t))
contents陣列用來實際儲存資料,陣列中元素的特性:無重複元素;元素在陣列中遞增排列。
整數集合相關API介紹
函式名稱 |
作用 |
複雜度 |
_intsetValueEncoding |
獲取給定整數的編碼型別 |
O(1) |
_intsetGet |
根據索引獲取整數值 |
O(1) |
_intsetSet |
根據索引設定給定整數值 |
O(1) |
intsetNew |
新建intset |
O(1) |
intsetResize |
為給定的intset重新分配記憶體 |
O(1) |
intsetSearch |
查詢給定的整數是否在intset中 |
O(logN) |
intsetUpgradeAndAdd |
先升級intset然後插入元素 |
O(N) |
intsetAdd |
直接新增元素 |
O(N) |
intsetMoveTail |
將intset中元素偏移 |
O(N) |
intsetRemove |
刪除元素 |
O(N) |
intsetRandom |
隨機返回一個intset中元素 |
O(1) |
intsetLen |
intset中元素的個數 |
O(1) |
intsetBlobLen |
intset所佔的位元組數 |
O(1) |
重要API原始碼的簡單解析
intsetAdd
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
//新增一個整數
intset
*intsetAdd(intset * is ,
int64_t value, uint8_t *success) {
uint8_t
valenc = _intsetValueEncoding(value); //得到型別的長度
uint32_t
pos;
if
(success) *success = 1;
/*
Upgrade encoding if necessary. If we need to upgrade, we know that
*
this value should be either appended (if > 0) or prepended (if < 0),
*
because it lies outside the range of existing values. */
//需要升級,那麼進行升級並插入新值
if
(valenc > intrev32ifbe(
|