Arrays 在展开链表中查找k-最小数的二进制搜索
我将序列存储在展开的链表中,以处理其他操作(插入、删除、反转),并在每个节点中的每个操作后维护排序数组,以实现高效的k-least查询。Arrays 在展开链表中查找k-最小数的二进制搜索,arrays,c,linked-list,binary-search,Arrays,C,Linked List,Binary Search,我将序列存储在展开的链表中,以处理其他操作(插入、删除、反转),并在每个节点中的每个操作后维护排序数组,以实现高效的k-least查询。 我使用了两种二进制搜索,一种是在k-least函数中,另一种是在lessunt和lessthanCount中。假设数字介于10^5和-10^5之间,第一类是确定mid是大于还是小于k-最小数。第二种是对每个节点进行二进制搜索并将结果相加,得到中间节点的顺序范围 我认为时间复杂度是O(lg(arraysize)*n/arraysize),我设置arraysize
我使用了两种二进制搜索,一种是在k-least函数中,另一种是在lessunt和lessthanCount中。假设数字介于10^5和-10^5之间,第一类是确定mid是大于还是小于k-最小数。第二种是对每个节点进行二进制搜索并将结果相加,得到中间节点的顺序范围 我认为时间复杂度是O(lg(arraysize)*n/arraysize),我设置arraysize=sqrt(n)以在k-least查询和其他操作之间取得平衡 然而,该计划仍然不够有效。有没有办法在不调整arraysize的情况下提高k-least查询操作
int lessCount(int x, LinkNode *node){
if (node->size == 0)
return 0;
int left = 0;
int right = node->size;
while (left < right){
int mid = (left + right) / 2;
if (node->sorted[mid] >= x){
right = mid;
}else if (node->sorted[mid] < x) {
left = mid + 1;
}
}
return left;
}
int lessthanCount(int x, LinkNode *node){
if (node->size == 0)
return 0;
int left = 0;
int right = node->size;
while (left < right){
int mid = (left + right) / 2;
if (node->sorted[mid] <= x) {
left = mid + 1;
}else if (node->sorted[mid] > x) {
right = mid;
}
}
return left;
}
int k_least(LinkNode *start, LinkNode *end, int nodeLen, int k){
LinkNode *ptr;
int max = 100001;
int min = -100000;
int mid = (max + min) / 2;
while (true){
int lower = 0, upper = 0;
ptr = start;
for (int i = 0; i < nodeLen; i++){
lower += lessCount(mid, ptr);
upper += lessthanCount(mid, ptr);
ptr = ptr->next;
}
lower += lessCount(mid, end);
upper += lessthanCount(mid, end);
if (k <= lower){
max = mid - 1;
mid = (max + min) / 2;
}else if (k > upper){
min = mid + 1;
mid = (max + min) / 2;
}else{
break;
}
}
return mid;
}
int-lessunt(int-x,LinkNode*node){
如果(节点->大小==0)
返回0;
int左=0;
int right=节点->大小;
while(左<右){
int mid=(左+右)/2;
如果(节点->排序的[mid]>=x){
右=中;
}else if(节点->已排序[中间]大小==0)
返回0;
int左=0;
int right=节点->大小;
while(左<右){
int mid=(左+右)/2;
如果(节点->已排序的[mid]已排序的[mid]>x){
右=中;
}
}
左转;
}
int k_最小值(LinkNode*开始,LinkNode*结束,int nodeLen,int k){
LinkNode*ptr;
int max=100001;
最小整数=-100000;
int mid=(最大+最小)/2;
while(true){
整数下限=0,上限=0;
ptr=启动;
for(int i=0;inext;
}
下部+=下部(中部、末端);
上限+=下限计数(中间、末端);
if(k上){
最小值=中间值+1;
中间=(最大+最小)/2;
}否则{
打破
}
}
中途返回;
}
它必须是一个展开的链表吗?考虑到有大量的操作(最多50000个),包括删除、插入和反转,并且序列长度可能高达50000,我想不出任何其他数据结构。我建议使用B-树。它与数组块具有相同的优势,但它也可以按排序顺序维护所有内容。您可以扩展它以存储每个节点中较小值的数量,并保持更新。还可以考虑自平衡搜索树族中的其他数据结构。