在算法技巧中有个著名的技巧叫做“哨兵”。这个技巧多用在线性搜索(从若干个数据中查找目标数据)等算法中。线性搜索的基本过程是将若干个数据从头到尾,依次逐个比对,知道找到目标数据。【1】
这是小白我在矢泽久雄的著作《计算机是怎样跑起来的》中读到的。
作者在书中列出了两个例子,一个是假设有100个箱子,箱子里面装有任意数字,箱子标有1-100的序号,然后从100个箱子之中查找是否有箱子装有写着要查找数字的纸条。
这个例子有一个需要关注的地方:这100个箱子有可能都没有装有这个数字。在这之前,我的解决方法和作者提出来的第一种方法一样。按照箱子序号从1到100,依次查询箱子的数字是否为目标数字。这个方法需要的步骤有:1.判断数字是否为目标数字;2.判断箱子序号是否在100以内。
这个方法每一次都要判断箱子的序号有没有到达100。
而运用哨兵技巧,则可以消除这种不必要的处理。作者添加了一个101号箱子,在这个箱子中放入目标数字。将这个数字称为“哨兵”。从1号箱子开始寻找,找到目标数字后,停止寻找。如果该箱子的序号小于101,则说明找到了该数字和对应的箱子;如果该箱子的序号为101,说明所有箱子都没有目标数字。
方法一:
#include<stdio.h>
int main()
{
int i;
int box[100];//box[100]={......}
int aim;
scanf("%d",&aim);
for(i=0;i<100&&aim!=box[i];i++);
if(i<100)
printf("此数在第%d个箱子内",i);
else
printf("不存在");
return 0;
}
方法二:
#include<stdio.h>
int main()
{
int i;
int box[101]; //box[101]={......,0}
int aim;
scanf("%d",&aim);
box[100]=aim;
for(i=0;aim!=box[i];i++);
if(i==100)
printf("不存在此数");
else
printf("此数在第%d个箱子内",i);
return 0;
}
作者举的第二个例子就更形象生动了!假设在某个伸手不见五指的夜晚,你站在距悬崖边缘100米的地方,地上每隔1米就任意放一件物品,请你找出这些物品中有没有苹果。
第一种方法是你每前进1米就要捡起地上的物品,检查是否拿到了苹果,同时还要检查有没有到达悬崖的边缘。第二种方法是将起点往后挪1米,在悬崖边上放置一个苹果。你每前进1米时只需要检查是不是苹果就好了,如果是苹果,再检查是不是到了悬崖边就行了。
这个例子大家可以将自己代入这个找苹果的游戏,就更能理解它所带来的便利了。
总之,我在书上看见这个技巧,觉得十分巧妙!
【1】引用《计算机是怎样跑起来的》矢泽久雄