1. 程式人生 > 程式設計 >Java 二分法檢索演算法程式碼實現詳解

Java 二分法檢索演算法程式碼實現詳解

一,二分法檢索演算法介紹

二分法檢索(binary search)又稱折半檢索,二分法檢索的基本思想是設字典中的元素從小到大有序地存放在陣列(array)中。是最常用的搜尋演算法之一,這主要是由於其搜尋時間短。

二,二分法檢索演算法思路

這種搜尋使用分而治之方法,並且需要事先對資料集進行排序。

它將輸入集合分為相等的兩半,並且每次迭代都將目標元素與中間元素進行比較。

如果找到該元素,則搜尋結束。否則,我們根據目標元素是小於還是大於中間元素,通過劃分並選擇適當的陣列分割槽來繼續尋找元素。

這就是為什麼對Binary Search有一個排序的集合很重要的原因。

當firstIndex(我們的指標)經過lastIndex(最後一個元素)時,搜尋將終止,這意味著我們已經搜尋了整個陣列,並且該元素不存在。

有兩種方法可以實現此演算法-迭代和遞迴。

這裡不應該是關於時間和空間這兩個實現之間複雜的差異,雖然這不成立於所有語言。

三,二分法檢索演算法程式碼實現

迭代式

首先讓我們看一下迭代方法:

public class SearchAlgorithms {
 /**
  *迭代方法
  * @param arr
  * @param elementToSearch
  * @return
  */
 public static int binarySearch(int arr[],int elementToSearch) {
 
  int firstIndex = 0;
  int lastIndex = arr.length - 1;
 
  // 終止條件(元素不存在)
  while(firstIndex <= lastIndex) {
   int middleIndex = (firstIndex + lastIndex) / 2;
   // 如果中間元素是我們的目標元素,那麼返回它的索引
   if (arr[middleIndex] == elementToSearch) {
    return middleIndex;
   }
 
   // 如果中間的元素比較小
   // 將我們的指數指向中間+1,不考慮前半部分
   else if (arr[middleIndex] < elementToSearch)
    firstIndex = middleIndex + 1;
 
    // 如果中間的元素更大
    // 將我們的指數指向中間1,不考慮下半部分
   else if (arr[middleIndex] > elementToSearch)
    lastIndex = middleIndex - 1;
 
  }
  return -1;
 }
 /**
  * 用於列印結果
  * @param targetParameter
  * @param index
  */
 public static void print(int targetParameter,int index) {
  if (index == -1){
   System.out.println(targetParameter + " 未找到");
  }
  else {
   System.out.println(targetParameter + " 搜尋結果為: " + index);
  }
 }
 //測試一下
 public static void main(String[] args) {
  int index = binarySearch(new int[]{89,57,91,47,95,3,27,22,67,99},67);
  print(67,index);
 }
}

輸出:

遞迴的

現在讓我們看一下遞迴實現:

遞迴方法的區別在於,一旦獲得新分割槽,我們便會呼叫方法本身。在迭代方法中,每當確定新分割槽時,我們都會修改第一個和最後一個元素,並在同一迴圈中重複該過程。

這裡的另一個區別是遞迴呼叫被推入方法呼叫堆疊,並且每個遞迴呼叫佔用一個空間單位。

我們可以像這樣使用這種演算法:

public class SearchAlgorithms {
 
 /**
  *遞迴方法
  * @param arr
  * @param elementToSearch
  * @return
  */
 public static int recursiveBinarySearch(int arr[],int firstElement,int lastElement,int elementToSearch) {
 
  // 結束條件
  if (lastElement >= firstElement) {
   int mid = firstElement + (lastElement - firstElement) / 2;
 
   // 如果中間元素是我們的目標元素,那麼返回它的索引
   if (arr[mid] == elementToSearch)
    return mid;
 
   // 如果中間元素大於目標元素
   if (arr[mid] > elementToSearch)
    return recursiveBinarySearch(arr,firstElement,mid - 1,elementToSearch);
 
   return recursiveBinarySearch(arr,mid + 1,lastElement,elementToSearch);
  }
 
  return -1;
 }
 /**
  * 用於列印結果
  * @param targetParameter
  * @param index
  */
 public static void print(int targetParameter,int index) {
  if (index == -1){
   System.out.println(targetParameter + " 未找到");
  }
  else {
   System.out.println(targetParameter + " 搜尋結果為: " + index);
  }
 }
 //測試一下
 public static void main(String[] args) {
  int index = recursiveBinarySearch(new int[]{3,89,10,index);
 }
}

輸出:

四,以演算法時間複雜度和空間複雜度總結演算法。

時間複雜度

由於二進位制搜尋每次將其時間複雜度為O(log(N))時都會將陣列分為兩半。此時間複雜度是線性搜尋O(N)時間複雜度的顯著改進。

空間複雜度

此搜尋僅需要一個空間單位即可儲存要搜尋的元素。因此,其空間複雜度為O(1)。

如果二分法檢索是遞迴實現的,則需要將對該方法的呼叫儲存在堆疊中。在最壞的情況下,這可能需要O(log(N))空間。

它是大多數用於搜尋的庫中最常用的搜尋演算法,二分法檢索樹也被許多儲存排序資料的資料結構所使用。

該Arrays.binarySearch方法中的Java API也實現了二進位制搜尋哦。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。