日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

redis之intset

發布時間:2025/6/15 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 redis之intset 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

? ? ? ? ?今天來學習一下redis里面的整數集合。

typedef struct intset { //結構體大小為8uint32_t encoding; //編碼方式uint32_t length; //數組長度int8_t contents[]; //數組下表從0開始 } intset;

encoding是contents數組元素的編碼方式,contents里面存儲整數。

/** Copyright (c) 2009-2012, Pieter Noordhuis <pcnoordhuis at gmail dot com>* Copyright (c) 2009-2012, Salvatore Sanfilippo <antirez at gmail dot com>* All rights reserved.** Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions are met:** * Redistributions of source code must retain the above copyright notice,* this list of conditions and the following disclaimer.* * Redistributions in binary form must reproduce the above copyright* notice, this list of conditions and the following disclaimer in the* documentation and/or other materials provided with the distribution.* * Neither the name of Redis nor the names of its contributors may be used* to endorse or promote products derived from this software without* specific prior written permission.** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE* POSSIBILITY OF SUCH DAMAGE.*/#include <stdio.h> #include <stdlib.h> #include <string.h> #include "intset.h" #include "zmalloc.h" #include "endianconv.h"/* Note that these encodings are ordered, so:* INTSET_ENC_INT16 < INTSET_ENC_INT32 < INTSET_ENC_INT64. */ #define INTSET_ENC_INT16 (sizeof(int16_t)) //2 #define INTSET_ENC_INT32 (sizeof(int32_t)) //4 #define INTSET_ENC_INT64 (sizeof(int64_t)) //8/* Return the required encoding for the provided value. */ static uint8_t _intsetValueEncoding(int64_t v) {//返回適用于傳入值v的編碼方式if (v < INT32_MIN || v > INT32_MAX)return INTSET_ENC_INT64;else if (v < INT16_MIN || v > INT16_MAX)return INTSET_ENC_INT32;elsereturn INTSET_ENC_INT16; }/* Return the value at pos, given an encoding. */ //根據給定的編碼方式enc,返回集合的底層數組在pos索引上的元素 static int64_t _intsetGetEncoded(intset *is, int pos, uint8_t enc) {int64_t v64;int32_t v32;int16_t v16;if (enc == INTSET_ENC_INT64) {memcpy(&v64,((int64_t*)is->contents)+pos,sizeof(v64));memrev64ifbe(&v64);return v64;} else if (enc == INTSET_ENC_INT32) {memcpy(&v32,((int32_t*)is->contents)+pos,sizeof(v32));memrev32ifbe(&v32);return v32;} else {memcpy(&v16,((int16_t*)is->contents)+pos,sizeof(v16));memrev16ifbe(&v16);return v16;} }/* Return the value at pos, using the configured encoding. */ static int64_t _intsetGet(intset *is, int pos) {//根據集合的編碼方式,返回底層數組在 pos 索引上的值return _intsetGetEncoded(is,pos,intrev32ifbe(is->encoding)); }/* Set the value at pos, using the configured encoding. */ static void _intsetSet(intset *is, int pos, int64_t value) {//根據集合的編碼方式,將底層數組在 pos 位置上的值設為 valueuint32_t encoding = intrev32ifbe(is->encoding);if (encoding == INTSET_ENC_INT64) {((int64_t*)is->contents)[pos] = value;memrev64ifbe(((int64_t*)is->contents)+pos);} else if (encoding == INTSET_ENC_INT32) {((int32_t*)is->contents)[pos] = value;memrev32ifbe(((int32_t*)is->contents)+pos);} else {((int16_t*)is->contents)[pos] = value;memrev16ifbe(((int16_t*)is->contents)+pos);} }/* Create an empty intset. */ intset *intsetNew(void) {//創建并返回一個新的空整數集合intset *is = zmalloc(sizeof(intset));is->encoding = intrev32ifbe(INTSET_ENC_INT16); //存儲字節序轉換is->length = 0;return is; }/* Resize the intset */ static intset *intsetResize(intset *is, uint32_t len) {//調整整數集合的內存空間大小uint32_t size = len*intrev32ifbe(is->encoding);is = zrealloc(is,sizeof(intset)+size);//sizeof(intset)是頭需要存儲的長度,size是數據的長度return is; }/* Search for the position of "value". Return 1 when the value was found and* sets "pos" to the position of the value within the intset. Return 0 when* the value is not present in the intset and sets "pos" to the position* where "value" can be inserted. *///在集合is的底層數組中查找值value所在的索引;成功找到value時,函數返回1,并將*pos的值設為value所在的索引//當在數組中沒找到 value 時,返回 0 。并將 *pos 的值設為 value 可以插入到數組中的位置。 static uint8_t intsetSearch(intset *is, int64_t value, uint32_t *pos) {//printf("---intsetSearch---%d,%d\n",value,*pos);int min = 0, max = intrev32ifbe(is->length)-1, mid = -1;int64_t cur = -1;/* The value can never be found when the set is empty */if (intrev32ifbe(is->length) == 0) { //為空的情況if (pos) *pos = 0;return 0;} else {/* Check for the case where we know we cannot find the value,* but do know the insert position. */if (value > _intsetGet(is,max)) { //和最后一個元素對比if (pos) *pos = intrev32ifbe(is->length);return 0;} else if (value < _intsetGet(is,0)) { //和第一個元素對比if (pos) *pos = 0;return 0;}}//二分查找while(max >= min) {mid = ((unsigned int)min + (unsigned int)max) >> 1;cur = _intsetGet(is,mid); //獲取值if (value > cur) {min = mid+1;} else if (value < cur) {max = mid-1;} else {break;}}if (value == cur) {if (pos) *pos = mid;return 1;} else {if (pos) *pos = min;return 0;} }/* Upgrades the intset to a larger encoding and inserts the given integer. */ //根據值 value 所使用的編碼方式,對整數集合的編碼進行升級,并將值 value 添加到升級后的整數集合中 static intset *intsetUpgradeAndAdd(intset *is, int64_t value) {uint8_t curenc = intrev32ifbe(is->encoding);//字節序轉換uint8_t newenc = _intsetValueEncoding(value); //新value需要的編碼int length = intrev32ifbe(is->length);int prepend = value < 0 ? 1 : 0; //添加前端或末尾/* First set new encoding and resize */is->encoding = intrev32ifbe(newenc); //改變編碼方式is = intsetResize(is,intrev32ifbe(is->length)+1); //調整大小 /* Upgrade back-to-front so we don't overwrite values.* Note that the "prepend" variable is used to make sure we have an empty* space at either the beginning or the end of the intset. */while(length--)_intsetSet(is,length+prepend,_intsetGetEncoded(is,length,curenc));//復制舊值/* Set the value at the beginning or the end. */if (prepend)_intsetSet(is,0,value);else_intsetSet(is,intrev32ifbe(is->length),value);is->length = intrev32ifbe(intrev32ifbe(is->length)+1);return is; }static void intsetMoveTail(intset *is, uint32_t from, uint32_t to) {//向前或先后移動指定索引范圍內的數組元素void *src, *dst;uint32_t bytes = intrev32ifbe(is->length)-from; //要移動元素的個數uint32_t encoding = intrev32ifbe(is->encoding);if (encoding == INTSET_ENC_INT64) {src = (int64_t*)is->contents+from;dst = (int64_t*)is->contents+to;bytes *= sizeof(int64_t);} else if (encoding == INTSET_ENC_INT32) {src = (int32_t*)is->contents+from;dst = (int32_t*)is->contents+to;bytes *= sizeof(int32_t);} else {src = (int16_t*)is->contents+from;dst = (int16_t*)is->contents+to;bytes *= sizeof(int16_t);}memmove(dst,src,bytes);//memmove能夠保證源串在被覆蓋之前將重疊區域的字節拷貝到目標區域中 }/* Insert an integer in the intset */ intset *intsetAdd(intset *is, int64_t value, uint8_t *success) {//嘗試將元素 value 添加到整數集合中uint8_t valenc = _intsetValueEncoding(value);uint32_t pos;if (success) *success = 1; //success指示添加是否成功/* 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. */printf("encoding =%d\n",intrev32ifbe(is->encoding)); if (valenc > intrev32ifbe(is->encoding)) { //判斷編碼方式/* This always succeeds, so we don't need to curry *success. */return intsetUpgradeAndAdd(is,value);} else {/* Abort if the value is already present in the set.* This call will populate "pos" with the right position to insert* the value when it cannot be found. */if (intsetSearch(is,value,&pos)) { //成功找到value返回1,沒找到返回0。并這只一個合適的pos值保證有序if (success) *success = 0;return is;}is = intsetResize(is,intrev32ifbe(is->length)+1);if (pos < intrev32ifbe(is->length)) intsetMoveTail(is,pos,pos+1);}_intsetSet(is,pos,value);is->length = intrev32ifbe(intrev32ifbe(is->length)+1);return is; }/* Delete integer from intset */ intset *intsetRemove(intset *is, int64_t value, int *success) {//從整數集合中刪除值valueuint8_t valenc = _intsetValueEncoding(value);uint32_t pos;if (success) *success = 0;if (valenc <= intrev32ifbe(is->encoding) && intsetSearch(is,value,&pos)) {uint32_t len = intrev32ifbe(is->length);/* We know we can delete */if (success) *success = 1;/* Overwrite value with tail and update length */if (pos < (len-1)) intsetMoveTail(is,pos+1,pos);is = intsetResize(is,len-1);is->length = intrev32ifbe(len-1);}return is; }/* Determine whether a value belongs to this set */ uint8_t intsetFind(intset *is, int64_t value) {//檢查給定值 value 是否集合中的元素uint8_t valenc = _intsetValueEncoding(value);return valenc <= intrev32ifbe(is->encoding) && intsetSearch(is,value,NULL); }/* Return random member */ int64_t intsetRandom(intset *is) {//從整數集合中隨機返回一個元素return _intsetGet(is,rand()%intrev32ifbe(is->length)); }/* Get the value at the given position. When this position is* out of range the function returns 0, when in range it returns 1. */ uint8_t intsetGet(intset *is, uint32_t pos, int64_t *value) {//取出集合底層數組指定位置中的值,并將它保存到value指針中if (pos < intrev32ifbe(is->length)) {*value = _intsetGet(is,pos);return 1;}return 0; }/* Return intset length */ uint32_t intsetLen(const intset *is) {//返回整數集合現有的元素個數return intrev32ifbe(is->length); }/* Return intset blob size in bytes. */ size_t intsetBlobLen(intset *is) {//返回整數集合現在占用的字節總數量return sizeof(intset)+intrev32ifbe(is->length)*intrev32ifbe(is->encoding); }

整數集合會根據整數大小選擇合適的編碼方式,很節約內存。

總結

以上是生活随笔為你收集整理的redis之intset的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲精品专区 | www.天天干| 秋霞影院一区二区 | 午夜丰满寂寞少妇精品 | 女性生殖扒开酷刑vk | 亚洲第一国产 | ass极品国模人体欣赏 | 久久久777| 亚洲精品高潮久久久久久久 | 在线成人福利 | 一级片视频在线观看 | 国产激情成人 | 久久精品成人一区二区三区蜜臀 | 小俊大肉大捧一进一出好爽 | 成人三级做爰av | 美女扒逼| 黄色综合网 | 尼姑福利影院 | 特级西西444www高清大胆免费看 | 日本一二三区视频在线 | 色综合久久中文字幕无码 | 亚洲狼人色 | 18视频在线观看网站 | 成人免费看视频 | 精品视频在线观看一区二区 | 黄视频网站在线观看 | 精品麻豆一区二区 | 播播网色播播 | 1000部做爰免费视频 | 山村大伦淫第1部分阅读小说 | 男生看的污网站 | 欧美特级a | 少妇高潮一区二区三区喷水 | 张津瑜国内精品www在线 | 日韩在线不卡av | 天天干天天综合 | 亚洲码国产精品高潮在线 | 波多野结衣50连登视频 | 国产午夜无码精品免费看奶水 | 国产在线精品一区二区 | 91传媒网站| 这里只有精品视频在线观看 | 亚洲精品一二三四 | 一区视频在线 | 高hnp视频 | 欧美激情成人在线 | 亚洲精品一区二 | 国产人妖ts | 黄色资源在线观看 | 国产精品久久久久久久9999 | 国产精品探花一区二区在线观看 | 亚洲图片另类小说 | 九九热视频精品 | 伊人春色在线视频 | 久久久久久久久久久久97 | 30一40一50老女人毛片 | 亚洲av无码乱码国产精品fc2 | 亚洲综合在线成人 | 夜夜躁狠狠躁 | 麻豆免费在线视频 | 曰韩av | 成人午夜视频在线观看 | 亚洲人成无码www久久久 | 777亚洲| 国产一区二区三区四区hd | 国产swag在线观看 | 99国产精品久久久久久久成人热 | 一本色道久久综合狠狠躁 | 天堂在线一区 | 中文字幕一区二区三区在线观看 | 午夜国产小视频 | 国产真实乱 | 国产精品一区在线观看你懂的 | 国产内射一区二区 | 无码精品国产一区二区三区免费 | 国精品一区二区 | 欧美综合色区 | 在线高清观看免费观看 | 我看黄色一级片 | 国产尻逼视频 | 葵司ssni-879在线播放 | 成人av观看 | 一区二区三区四区人妻 | 操亚洲| 免费观看全黄做爰的视频 | 性生活网址 | 亚洲精品xxxxx | 亚洲中文一区二区 | 国产精品传媒一区二区 | 欧美久久久久久久 | 精品黄色片 | 91精品观看 | 色八戒av| 精品久久免费 | 亚洲日本欧美 | 久久国产影院 | 伊人久久大香线蕉 | 中文在线字幕av | 在厨房拨开内裤进入毛片 |