Algorithm 这个线性搜索实现真的有用吗?

Algorithm 这个线性搜索实现真的有用吗?,algorithm,Algorithm,在中,我发现了这个有趣的线性搜索实现(实际上是我的Java实现;-): 它基本上使用了sentinel,这是搜索的值,因此您总是可以找到值,而不必检查数组边界。最后一个元素存储在一个temp变量中,然后将sentinel放置在最后一个位置。当找到该值时(记住,由于sentinel,它总是被找到),原始元素将被还原,并且索引将被检查,如果它表示最后一个索引并且与搜索到的值不相等。如果是这种情况,则返回-1(不包含),否则返回索引 虽然我发现这个实现非常聪明,但我想知道它是否真的有用。对于小型阵列,

在中,我发现了这个有趣的线性搜索实现(实际上是我的Java实现;-):

它基本上使用了sentinel,这是搜索的值,因此您总是可以找到值,而不必检查数组边界。最后一个元素存储在一个temp变量中,然后将sentinel放置在最后一个位置。当找到该值时(记住,由于sentinel,它总是被找到),原始元素将被还原,并且索引将被检查,如果它表示最后一个索引并且与搜索到的值不相等。如果是这种情况,则返回-1(不包含),否则返回索引

虽然我发现这个实现非常聪明,但我想知道它是否真的有用。对于小型阵列,它似乎总是较慢,而对于大型阵列,只有在找不到该值时,它似乎才较快。有什么想法吗

编辑


原始的实现是用C++编写的,所以可以有所作为。

< P>一个前哨搜索回到Knuth。它的价值在于将循环中的测试数量从两个(“键匹配吗?我在末尾吗?”)减少到一个

是的,它很有用,因为它可以通过消除条件分支预测失误,大大减少中等大小无序数组的搜索时间。这还减少了此类数组的插入时间(OP未显示代码),因为您不必订购这些项目

如果有序项的数组较大,则二进制搜索会更快,但代价是插入时间较长,以确保数组有序

对于更大的集合,哈希表将是最快的


真正的问题是阵列大小的分布是什么?

哨兵搜索可以追溯到Knuth。它的价值在于将循环中的测试数量从两个(“键匹配吗?我在末尾吗?”)减少到一个

是的,它很有用,因为它可以通过消除条件分支预测失误,大大减少中等大小无序数组的搜索时间。这还减少了此类数组的插入时间(OP未显示代码),因为您不必订购这些项目

如果有序项的数组较大,则二进制搜索会更快,但代价是插入时间较长,以确保数组有序

对于更大的集合,哈希表将是最快的


真正的问题是阵列大小的分布是什么?

似乎并不特别有用。这里的“创新”仅仅是通过将迭代测试与匹配测试相结合来摆脱迭代测试。如今,现代处理器在迭代检查上花费的时间为0(所有的计算和分支都与匹配测试代码并行完成)


在任何情况下,二进制搜索在大型数组上都比这段代码好,在小型数组上也比得上。线性搜索非常有用。

似乎不是特别有用。这里的“创新”仅仅是通过将迭代测试与匹配测试相结合来摆脱迭代测试。如今,现代处理器在迭代检查上花费的时间为0(所有的计算和分支都与匹配测试代码并行完成)


在任何情况下,二进制搜索在大型数组上都比这段代码好,在小型数组上也比得上。线性搜索是如此的简单。

它不是线程安全的,例如,在第一个线程将
a[high]
更改为
key
后,通过第二个线程开始,您可能会丢失
a[high]
值,因此将
key
记录到
tmp
,并在第一个线程恢复
a[high]后完成
恢复到其原始值。第二个线程将
a[high]
恢复到它第一次看到的状态,这是第一个线程的


它在java中也没有用处,因为JVM将在数组中包含边界检查,所以while循环检查数组是否没有结束。

它不是线程安全的,例如,您可能会丢失
a[high]
值通过在第一个线程将
a[high]
更改为
key
后开始第二个线程,因此将
key
记录为
tmp
,并在第一个线程将
a[high]
恢复为其原始值后结束。第二个线程将
a[high]
恢复到它第一次看到的状态,这是第一个线程的


它在java中也没有用处,因为JVM将在数组中包含边界检查,所以while循环检查数组是否没有结束。

另请参阅“在非洲寻找老虎”笑话。

Punchline=一位经验丰富的程序员在开罗放置一只老虎,以便搜索终止。

另请参见“在非洲寻找老虎”的笑话。

Punchline=一个有经验的程序员在开罗放了一只老虎,这样搜索就终止了。

你会注意到这会增加速度吗?没有

你会注意到缺乏可读性吗?对

您是否会注意到可能导致并发问题的不必要的数组变异?对


过早优化是万恶之源。

你会注意到由此带来的速度提升吗?没有

你会注意到缺乏可读性吗?对

您是否会注意到可能导致并发问题的不必要的数组变异?对


过早优化是万恶之源。

是的,因为while循环与标准搜索相比没有两个比较


它的速度是原来的两倍。在Knuth第3卷中作为优化给出了它。

是的,因为while循环没有2个与标准搜索相反的比较


它的速度是原来的两倍。在Knuth第三卷中作为优化给出了它。

“它似乎总是比较慢…更快…”相对于什么替代方案?Sry,我的意思是与标准相比
public static int linearSearch(int[] a, int key) {
    int high = a.length - 1;
    int tmp  = a[high];

    // put a sentinel at the end of the array   
    a[high] = key;

    int i = 0;

    while (a[i] != key) {
        i++;
    }

    // restore original value
    a[high] = tmp;

    if (i == high && key != tmp) {
        return NOT_CONTAINED;
    }

    return i;
}