/* Search for the position of "value".
 *
 * 在集合is的底层数组中查找值value所在的索引。
 *
 * Return 1 when the value was found and
 * sets "pos" to the position of the value within the intset.
 *
 * 成功找到value时,函数返回1,并将*pos的值设为value所在的索引。
 *
 * Return 0 when
 * the value is not present in the intset and sets "pos" to the position
 * where "value" can be inserted.
 *
 * 当在数组中没找到value时,返回0。
 * 并将*pos的值设为value可以插入到数组中的位置。
 *
 * T = O(logN)
 */
static uint8_t intsetSearch(intset *is, int64_t value, uint32_t *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 */
    // 处理is为空时的函数
    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. */
    	// 因为底层数组是有序的,如果value比数组中最后一个值都要大
    	// 那么value肯定不存在于集合中,并且应该将value添加到底层数组的最末端
        if (value > _intsetGet(is,intrev32ifbe(is->length)-1)) {
            if (pos) *pos = intrev32ifbe(is->length);
            return 0;
        // 因为底层数组是有序的,如果value比数组中最前一个值都要小
        // 那么value肯定不存在于集合中,并且应该将它添加到底层数组的最前端
        } else if (value < _intsetGet(is,0)) {
            if (pos) *pos = 0;
            return 0;
        }
    }

    // 在有序数组中进行二分查找
    // T = O(logN)
    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;
        }
    }

    // 检查是否已经找到了value
    if (value == cur) {
        if (pos) *pos = mid;
        return 1;
    } else {
        if (pos) *pos = min;
        return 0;
    }
}
示例#2
0
文件: intset.c 项目: sdboyer/redis
void intsetRepr(intset *is) {
    int i;
    for (i = 0; i < is->length; i++) {
        printf("%lld\n", (uint64_t)_intsetGet(is,i));
    }
    printf("\n");
}
示例#3
0
文件: intset.c 项目: sdboyer/redis
/* Sets the value to 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) {
    if (pos < is->length) {
        *value = _intsetGet(is,pos);
        return 1;
    }
    return 0;
}
示例#4
0
文件: intset.c 项目: LC2010/note
/*
 * 查找 value 在 is 中的索引
 *
 * 查找成功时,将索引保存到 pos ,并返回 1 。
 * 查找失败时,返回 0 ,并将 value 可以插入的索引保存到 pos 。
 *
 * T = O(lg N)
 */
static uint8_t intsetSearch(intset *is, int64_t value, uint32_t *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) {
        // is 为空时,总是查找失败
        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,intrev32ifbe(is->length)-1)) {
            // 值比 is 中的最后一个值(所有元素中的最大值)要大
            // 那么这个值应该插入到 is 最后
            if (pos) *pos = intrev32ifbe(is->length);
            return 0;
        } else if (value < _intsetGet(is,0)) {
            // value 作为新的最小值,插入到 is 最前
            if (pos) *pos = 0;
            return 0;
        }
    }

    // 在 is 元素数组中进行二分查找 
    while(max >= min) {
        mid = (min+max)/2;
        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;
    }
}
示例#5
0
/* 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.
 *
 * 在intset中找到value所在位置。
 * 如果找到就返回1并且将pos的值设为value所在位置
 * 如果没找到就返回0并且将pos的值设为value应该插入的位置
 * */
static uint8_t intsetSearch(intset *is, int64_t value, uint32_t *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) {
    	//空集时直接返回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,intrev32ifbe(is->length)-1)) {
        	//整数集为有序集,最后一个元素为最大的数,比它还大则说明value不在集合中
            if (pos) *pos = intrev32ifbe(is->length);
            return 0;
        } else if (value < _intsetGet(is,0)) {
        	//第一个元素为最小值,比它小则说明value不在集合中
            if (pos) *pos = 0;
            return 0;
        }
    }

    //使用二分法查找元素
    while(max >= min) {
        mid = (min+max)/2;
        cur = _intsetGet(is,mid);
        if (value > cur) {
            min = mid+1;
        } else if (value < cur) {
            max = mid-1;
        } else {
            break;
        }
    }

    if (value == cur) {
    	//找到元素,将pos设为mid
        if (pos) *pos = mid;
        return 1;
    } else {
    	//没找到元素,将pos设为min即该插入得位置
        if (pos) *pos = min;
        return 0;
    }
}
示例#6
0
/* 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. */
static uint8_t intsetSearch(intset *is, int64_t value, uint32_t *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. */
        // value 比最大元素还大
        if (value > _intsetGet(is,intrev32ifbe(is->length)-1)) {
            if (pos) *pos = intrev32ifbe(is->length);
            return 0;
        // value 比最小元素还小
        } else if (value < _intsetGet(is,0)) {
            if (pos) *pos = 0;
            return 0;
        }
    }

    // 二分查找
    while(max >= min) {
        mid = (min+max)/2;
        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;
    }
}
示例#7
0
文件: intset.c 项目: Coder-chen/redis
static uint8_t intsetSearch(intset *is, int64_t value, uint32_t *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) {  // set 为空
        if (pos) *pos = 0;
        return 0;
    } else {                              // set 不为空
        /* Check for the case where we know we cannot find the value,
         * but do know the insert position. */

		// intset 中存储的数是按从小到大的顺序存储的  
        if (value > _intsetGet(is,intrev32ifbe(is->length)-1)) {
            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;  // 除2
        cur = _intsetGet(is,mid);                            // 获取值得大小                
        if (value > cur) {
            min = mid+1;                                     // 每次加减一位
        } else if (value < cur) {
            max = mid-1;
        } else {
            break;
        }
    }                           // 跳出循环 max < min 
      
    if (value == cur) {
        if (pos) *pos = mid;     
        return 1;                // 找到 
    } else {
        if (pos) *pos = min;       
        return 0;                // 没有找到
    }
}
/*
 * 取出集合底层数组指定位置中的值,并将它保存到value指针中。
 *
 * 如果pos没超过数组的索引范围,那么返回-1,如果超出索引,那么返回0。
 *
 * p.s.上面原文的文档说这个函数用于设置值,这是错误的。
 *
 * T = O(1)
 */
uint8_t intsetGet(intset *is, uint32_t pos, int64_t *value) {
	// pos < intrev32ifbe(is->length)
	// 检查pos是否符合数组的范围
    if (pos < intrev32ifbe(is->length)) {
    	// 保存值到指针
        *value = _intsetGet(is,pos);
        // 返回成功指示值
        return 1;
    }
    // 超出索引范围
    return 0;
}
示例#9
0
文件: intset.c 项目: sdboyer/redis
/* Return random member */
int64_t intsetRandom(intset *is) {
    return _intsetGet(is,rand()%is->length);
}
示例#10
0
文件: intset.c 项目: LC2010/note
/*
 * 随机返回一个 intset 里的元素
 *
 * T = theta(1)
 */
int64_t intsetRandom(intset *is) {
    return _intsetGet(is,rand()%intrev32ifbe(is->length));
}
示例#11
0
static void intsetRepr(intset *is) {
    for (uint32_t i = 0; i < intrev32ifbe(is->length); i++) {
        printf("%lld\n", (uint64_t)_intsetGet(is,i));
    }
    printf("\n");
}
/* Return random member
 *
 * 从整数集合中随机返回一个元素
 *
 * 只能在集合非空时使用
 *
 * T = O(1)
 */
int64_t intsetRandom(intset *is) {
	// intrev32ifbe(is->length)取出集合的元素数量
	// 而rand() % intrev32ifbe(is->length)根据元素数量计算一个随机索引
	// 然后_intsetGet负责根据随机索引来查找值
    return _intsetGet(is,rand()%intrev32ifbe(is->length));
}