Performance 如何在块的链表(包含n个元素)中尽快找到元素?

Performance 如何在块的链表(包含n个元素)中尽快找到元素?,performance,linked-list,arm,bit-manipulation,Performance,Linked List,Arm,Bit Manipulation,我的数据结构是块的链接列表。一个块包含31个4字节的元素和一个指向下一个块或NULL的4字节指针(每个块总计128字节)。我不时地添加元素。如果最后一个块已满,我将通过指针添加另一个块 一个目标是使用尽可能少的内存(=块),并且块中两个元素之间没有可用空间 此设置已修复。所有代码都在32位ARM Cortex-A8 CPU上运行,带有霓虹灯管道 问题: 如何在该数据结构中尽快找到特定元素 方法(现在): 我使用排序块和二进制搜索来检查元素(4字节中的9位是搜索条件)。如果所需元素不在当前块中,我

我的数据结构是块的链接列表。一个块包含31个4字节的元素和一个指向下一个块或NULL的4字节指针(每个块总计128字节)。我不时地添加元素。如果最后一个块已满,我将通过指针添加另一个块

一个目标是使用尽可能少的内存(=块),并且块中两个元素之间没有可用空间

此设置已修复。所有代码都在32位ARM Cortex-A8 CPU上运行,带有霓虹灯管道

问题: 如何在该数据结构中尽快找到特定元素

方法(现在): 我使用排序块和二进制搜索来检查元素(4字节中的9位是搜索条件)。如果所需元素不在当前块中,我跳到下一个块。如果元素不在最后一个块中,并且最后一个块尚未满,我将使用二进制搜索的结果插入新元素(如有必要,我将在此块中使用memmove腾出空间)。因此,所有的块总是被排序的

你有没有办法加快速度? 这就是我现在搜索的方式:(q->getPosition()是一个内联函数,它通过“&位掩码”从元素中提取9位位置)


由于大部分时间都花在块内搜索上,因此需要尽可能快地进行搜索。由于元素的数量是固定的,因此可以完全展开该循环,如中所示:

if (key < a[16]){
  if (key < a[8]){
    ...
  }
  else { // key >= a[8] && key < a[16]
    ...
  }
}
else { // key >= a[16]
  if (key < a[24]){
    ...
  }
  else { // key >= a[24]
    ...
  }
}
if(键=a[8]&&key=a[16]
如果(键=a[24]
...
}
}
研究生成的汇编语言并在调试器中单步执行,以确保编译器为您提供良好的代码

您可能需要编写一个小程序来打印上面的代码,因为手工编写或使用宏生成代码都很困难

补充:刚刚注意到你的9位搜索标准。在这种情况下,只需预先分配一个包含512个4字节字的数组,并直接对其进行索引。这是最快的,也是最少的代码

还添加了:如果需要保留块结构,还有另一种方法可以执行展开的二进制搜索。这是Jon Bentley的方法:

i = 0;
if (key >= a[i+16]) i += 16;
if (key >= a[i+ 8]) i +=  8;
if (key >= a[i+ 4]) i +=  4;
if (key >= a[i+ 2]) i +=  2;
if (i < 30 && key >= a[i+ 1]) i +=  1; // this excludes 31
if (key == a[i]) // then key is found
i=0;
如果(键>=a[i+16])i+=16;
如果(键>=a[i+8])i+=8;
如果(键>=a[i+4])i+=4;
如果(键>=a[i+2])i+=2;
如果(i<30&&key>=a[i+1])i+=1;//这不包括31人
如果(key==a[i])//则找到key

这比上面的if树要慢,因为操作
i
,但可能会大大减少代码量。

因为大部分时间都花在块内搜索上,所以需要尽可能快。由于元素的数量是固定的,因此可以完全展开该循环,如中所示:

if (key < a[16]){
  if (key < a[8]){
    ...
  }
  else { // key >= a[8] && key < a[16]
    ...
  }
}
else { // key >= a[16]
  if (key < a[24]){
    ...
  }
  else { // key >= a[24]
    ...
  }
}
if(键=a[8]&&key=a[16]
如果(键=a[24]
...
}
}
研究生成的汇编语言并在调试器中单步执行,以确保编译器为您提供良好的代码

您可能需要编写一个小程序来打印上面的代码,因为手工编写或使用宏生成代码都很困难

补充:刚刚注意到你的9位搜索标准。在这种情况下,只需预先分配一个包含512个4字节字的数组,并直接对其进行索引。这是最快的,也是最少的代码

还添加了:如果需要保留块结构,还有另一种方法可以执行展开的二进制搜索。这是Jon Bentley的方法:

i = 0;
if (key >= a[i+16]) i += 16;
if (key >= a[i+ 8]) i +=  8;
if (key >= a[i+ 4]) i +=  4;
if (key >= a[i+ 2]) i +=  2;
if (i < 30 && key >= a[i+ 1]) i +=  1; // this excludes 31
if (key == a[i]) // then key is found
i=0;
如果(键>=a[i+16])i+=16;
如果(键>=a[i+8])i+=8;
如果(键>=a[i+4])i+=4;
如果(键>=a[i+2])i+=2;
如果(i<30&&key>=a[i+1])i+=1;//这不包括31人
如果(key==a[i])//则找到key

这比上面的if树慢,因为操作了
i
,但可能会大大减少代码量。

让每个块中的元素数为m,当前列表中的块总数为n。那么,您算法的当前时间复杂度是O(n logm)

如果在将元素添加到块中后无法移动它们,那么我认为在时间复杂性方面,您无法做得比您已经做的更好。(您可以跟踪块中的最大和最小元素,如果元素不在此范围内,则跳过这些块。但这不会给您带来太多好处。这也会浪费空间跟踪每个块的最小和最大元素)

如果您可以在插入元素时花费时间,并且可以将元素从一个块移动到另一个块,那么下面是一个时间复杂度为O(log(mn))的方案


基本上,所有元素都是按顺序排列的。当必须插入新元素时,跨块边界进行二进制搜索并将其插入到正确的位置,移动元素以创建空间。这将导致插入元素时的O(nm)时间,而查找元素时的O(log(mn))时间

让每个块中的元素数为m,当前列表中的块总数为n。那么,您算法的当前时间复杂度是O(n logm)

如果在将元素添加到块中后无法移动它们,那么我认为在时间复杂性方面,您无法做得比您已经做的更好。(您可以跟踪块中的最大和最小元素,如果元素不在此范围内,则跳过这些块。但这不会给您带来太多好处。这也会浪费空间跟踪每个块的最小和最大元素)

如果您可以在插入元素时花费时间,并且可以将元素从一个块移动到另一个块,那么下面是一个时间复杂度为O(log(mn))的方案

基本上,所有元素都是按顺序排列的。Wh