/* 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; } }
void intsetRepr(intset *is) { int i; for (i = 0; i < is->length; i++) { printf("%lld\n", (uint64_t)_intsetGet(is,i)); } printf("\n"); }
/* 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; }
/* * 查找 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; } }
/* 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; } }
/* 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; } }
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; }
/* Return random member */ int64_t intsetRandom(intset *is) { return _intsetGet(is,rand()%is->length); }
/* * 随机返回一个 intset 里的元素 * * T = theta(1) */ int64_t intsetRandom(intset *is) { return _intsetGet(is,rand()%intrev32ifbe(is->length)); }
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)); }