以数组为对象的两种查找方法对比。
线性查找可以针对任何数组,将数组中的每项依次遍历出来之后,与所要查找项对比。
消耗时间也是不规律的,可能查找项处于数组的第一位,也可能处于数组的最后一位。还有可能数组中完全不存在需要查找的项目。
二分查找法,针对有序数组使用。
因为数组已经有序排列,可以通过将数组从中间分割,将中间项与所需查找项对比;然后再根据对比结果,再次向上或者向下,寻找中间项对比,直至完成查找。
而且,对于查找最开始,可以通过与第一项和最末项的对比,确定查找项是否处于此数组中。
线性查找:
自定义一个10位的 int[ ] 数组;
public class xianxing {
private static int[] array;
public static void main(String[] args) {
initArray();
queryArray(56);
}
private static void initArray() {
// 方便和线性查找对比,将数组静态定义
array = new int[] { 38, 4, 54, 6, 7, 23, 9, 34, 56, 13 };
// for (int i = 0; i < array.length; i++) {
// array[i] = (int) (Math.random()*100);
// System.out.println("array的第"+i+"位的值为"+array[i]);
// }
}
private static void queryArray(int i) {
// TODO Auto-generated method stub
for (int j = 0; j < array.length; j++) {
if (56 == array[j]) {
System.out.println("共计查找次数" + (j + 1) + "次");
}
}
}
}
我们可以看出面对无序数组,查找消耗的比较次数完全是随机的,但是在多次查找之后,可以得出结论:
平均下来的查找次数为N/2;N为数组的长度。
那么面对有序数组使用二分查找法呢?
二分查找:
我们需要将数组重新排序:使用插入排序为数组排序
private static void initandSortArray() {
// TODO Auto-generated method stub
array = new int[] { 38, 4, 54, 6, 7, 23, 9, 34, 56, 13 };
System.out.println("排序前的数组:{ 38, 4, 54, 6, 7, 23, 9, 34, 56, 13 }");
SortArray();
// for (int i = 0; i < array.length; i++) {
// array[i] = (int) (Math.random()*100);
// System.out.println("array的第"+i+"位的值为"+array[i]);
// }
}
private static void SortArray() {
// TODO Auto-generated method stub
int in, out;
for (out = 1; out < array.length; out++) { // 被选中暂时移出数组的项
int temp = array[out]; // 零时值接受out位置的值
in = out; // 将out前的项整体前移
while (in > 0 && array[in - 1] >= temp) {
// 将暂时被移除的项与之间的局部已排序的局部列表对比
array[in] = array[in - 1];
--in;
}
array[in] = temp;
}
System.out.println("排序后的数组:{");
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]+",");
}
}
输出结果如下:
排序前的数组:{ 38, 4, 54, 6, 7, 23, 9, 34, 56, 13 }
排序后的数组:{
4,6,7,9,13,23,34,38,54,56,
那么看来我们的排序生效了,接下来重写查找方法,使用二分查找法
private static void queryArray(int i) {
int lowerBound, upperBound;
lowerBound = 0;// array的起始位置
upperBound = array.length - 1;// array的结束位置
int currentLoca;// 目标位置
if (array[lowerBound] <= i && array[upperBound] >= i
&& upperBound >= upperBound)// 已知从小到大的排序可以加上此判断
{
int queryCount = 0;//查找计数器
while (true) {
queryCount++;
currentLoca = (lowerBound + upperBound) / 2;
if (array[currentLoca] == i) {
System.out.println("已经查找到,目标位置:" + currentLoca+";查找次数为"+queryCount);
return;
} else {
if (array[currentLoca] < i) {
lowerBound = currentLoca + 1;// 查找范围向上移动
} else {
upperBound = currentLoca - 1;// 查找范围向下移动
}
}
}
}
}
已经查找到,目标位置:9;查找次数为4
对比结论:
线性查找:查找次数平均为N/2.
二分查找:查找次数在10位的数组中最大数为4(运气好的好,也许第一次就找到了)。
那么这样看,线性查找只是比二分查找多了一次查找而已,并没有看出二分查找的优势。
如果我们将数组基数放大:
那么当数组的基数放大时,线性查找次数将会成正比增长,K=N/2;
而二分查找,我们通过一个公式来表达,K=㏒2(N),对数计算给出了二分查找法最大耗费的次数。
那么N/2与㏒2(N)对比之下,差异性就显现了。