本文為joshua317原創文章,轉載請注明:轉載自joshua317博客 https://www.joshua317.com/article/130
一、二分查找簡述
折半查找(Binary Search)又稱為二分查找,其要求數據序列呈線性結構,也就是經過排序的數據序列。對於沒有經過排序的數據序列,可以先進行排序操作,然后執行折半查找操作。它是一種效率較高的查找方法。但二分查找有一定的條件限制:要求線性表必須采用順序存儲結構,且表中元素必須按關鍵字有序(升序或降序均可)。
二、二分查找分析
折半查找的基本思路是:
在有序表中,取中間的記錄作為比較對象
(1)如果要查找的值等於中間索引對應的值,則查找成功。
(2)若中間索引對應的值大於要查找的值,則在中間索引的前半部分繼續查找。
(3)若中間索引對應的值小於要查找的值,則在中間索引的后半部分繼續查找。
(4)不斷重述上述查找過程,直到查找成功,或有序表中沒有所要查找的值,查找失敗。
具體操作過程如下:
現在我們有一個有序的整型數組listData,然后設置兩個變量,一個是low,指向數組第1個索引的位置,即:low=0;另一個是high,指向數組最后一個索引的位置,即:high=listData.length-1。
設要查找的值為value。當low≤high時,反復執行以下步驟:
(1)計算中間索引的位置mid,mid=(low+high)/2。
(2)將待查找的值value和listData[middle]進行比較。
① 若listData[middle] == value,查找成功,middle所指元素即為要查找的元素。
② 若listData[middle] > value,說明若存在要查找的值,該值一定在查找有序數組的前半部分。修改查找范圍的上界:high=middle-1,轉(1)。
③ 若listData[middle] < value,說明若存在要查找的值,該值一定在查找有序數組的后半部分。修改查找范圍的下界:low=middle+1,轉(1)。
重復以上過程,當low>high時,表示查找失敗。
接下來我們用圖文的形式分下查找的過程:
現在有一組有序的整型數據為{2, 12, 15, 23, 25, 28, 39, 40,46,66}
若要查找value=39的記錄,則折半查找過程如下。
(1)初始時
low=0;
high=9;
mid=(low+high)/2, middle=4;
listData[middle]=25;
(2)比較listData[middle]和value,由於listData[middle] < 46,下一步到后半部分查找,於是
low=middle+1,low=5;
high依舊為9, high=9;
mid=(low+high)/2, middle=7;
listData[middle]=40;
(3)比較listData[middle]和value,由於listData[middle] > 39,下一步到前半部分查找,於是
low依舊為5, low=5;
high=middle-1, high=6;
mid=(low+high)/2, middle=5;
listData[middle]=28;
(4)比較listData[middle]和value,由於listData[middle] < 39,下一步到后半部分查找,於是
low=middle+1,low=6;
high依舊為6, high=6;
mid=(low+high)/2,middle=6;
listData[middle]=39;
(5)比較listData[middle]和value,由於listData[middle] == 39,查找成功,返回索引,結束。
三、二分查找的實現
package com.joshua317;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
/*
System.out.println("折半查找算法實例");
System.out.println("請輸入十個有序的整型數據");
int[] listData = new int[10];
Scanner scanner = new Scanner(System.in);
// 接收數據
for (int i = 0; i < listData.length; i++) {
listData[i] = scanner.nextInt();
}
// 打印所有數組元素
System.out.print("輸入的數據為:");
for (int i = 0; i < listData.length; i++) {
System.out.print(listData[i] + ",");
}
System.out.println();
System.out.println("請輸入要查找的數據");
int value = scanner.nextInt();
*/
int[] listData = {2, 12, 15, 23, 25, 28, 39, 40,46,66};
int value = 39;
int index = binarySearch(listData, value);
if (index != -1) {
System.out.println("在第" + (index+1) + "個位置,數據:" + listData[index]);
} else {
System.out.println("數據未找到");
}
}
public static int binarySearch(int[] listData, int value)
{
int low, middle, high;
low = 0;
high = listData.length - 1;
while (low <= high) {
middle = (low + high) / 2;
System.out.printf("low=%d,high=%d,middle=%d,listData[middle]=%d", low, high, middle, listData[middle]);
System.out.println();
if (listData[middle] == value) {
return middle;
} else if (listData[middle] > value) {
high = middle - 1;
} else if (listData[middle] < value) {
low = middle + 1;
}
}
return -1;
}
}
四、最后
折半查找的優點是比較次數較順序查找要少,查找速度較快,執行效率較高。缺點是表的存儲結構只能為順序存儲,不能為鏈式存儲,且表中元素必須是有序的。折半查找成功時的平均查找長度log2(n+1)-1,它的時間復雜度為O(log2n)
本文為joshua317原創文章,轉載請注明:轉載自joshua317博客 https://www.joshua317.com/article/130