我们知道,查找算法中有顺序查找和二分查找。本篇博客介绍一下哨兵查找算法,哨兵查找算法是对顺序查找的一个优化。
哨兵查找算法?
想要了解什么是哨兵查找算法,我们先来看一个普通的顺序查找的代码。
查找一个元素在数组中的下标,如果存在返回其下标,不存在返回-1。
public static int seqSearch(int[] arr, int target) {
int length = arr.length;
for (int i = 0; i < length; ++i) {
if (arr[i] == target) {
return i;
}
}
return -1;
}
上述程序是一个典型的顺序查找代码,但是在这个循环体中会有两次的判断,也就是i < lenght;
和arr[i] == target
。而哨兵查找算法的循环体中只需要一个判断语句。如果数组长度很长的场景,哨兵查找算法的效率会高一些。
下面,我们来看一下哨兵查找的代码。
public static int sentrySearch(int[] arr, int target) {
if (target == arr[0]) {
return 0;
}
// 将第一个元素保存
int temp = arr[0];
// 将目标值放到0号下标出作为哨兵
arr[0] = target;
int index = arr.length - 1;
while (arr[index] != target) {
--index;
}
// 查找完毕,将0号下标元素还原
arr[0] = temp;
return index > 0 ? index : -1;
}
从代码上可以看出,哨兵查找算法的思路大致如下:
- 首先,判断0号下标元素是否和目标值相同,如果相同,直接返回0;
- 如果不同,则我们将0号下标元素先保存起来,然后将目标值放到0号下标处;
- 然后,我们从后向前查找,如果和目标值相同,则结束循环,否则向前走。当下标为0时,会结束循环,因为0号下标是目标值;
- 查找完毕后,我们将前面保存的0号下标的值再还原回去;
- 最后判断index是否大于0,如果大于0表示找到了,否则就是没找到。