1. 程式人生 > >演算法-二分查詢1

演算法-二分查詢1

如何最省記憶體實現快速查詢

二分查詢也叫折半查詢,是一種針對有序集合的查詢演算法。

二分查詢的思想:在長度為 n 的陣列最中查詢值等於 m 的元素位置,先用陣列中間位置 mid 上的元素與其相比。等於 m 則返回 mid 的值,如果小於 m 則在陣列 0 至 mid-1 區間上按照此方法繼續比較查詢,如果大於 m 則在陣列 mid + 1 至 n 區間上按照此方法據需比較查詢。

通過上述描述,我們能發現二分查詢其實也是運用的遞迴的方法。遞推公式:search(list[low,high]) =serch(list[low,mid - 1]),search(list[mid + 1,high]),終止條件:low > high

二分查詢遞迴程式碼實現:
	public static int dserch(int[] list,int low,int high,int num){
		if(low > high){
			return -1;
		}
		int mid = (low + high)/2;
		if(list[mid] == num){
			return mid;
		}else if(list[mid] < num){
			return dserch(list,low + 1,high,num);
		}
		else{
			return dserch(list,low + 1
,high,num); } }
二分查詢非遞迴程式碼實現:
	public static int search(int[] list,int num){
		int low = 0;
		int high = list.length - 1;
		while(low <= high){
			int mid = (high + low)/2;
			if(list[mid] == num){
				return mid;
			}else if(list[mid] > num){
				high = mid - 1;
			}else{
				low = mid +
1; } } return -1; }

上述程式碼中需要注意的幾點:

1:迴圈退出條件:low < high
2:mid 的取值。如果是 mid = (low + high)/2,有可能會值會過大溢位。可以使用下面寫法:mid = low + (high - low)/2,如果追求效能優化到極致,可以使用下面寫法:mid = low +((high - low)>>1)。相對於除法,計算機執行位運算效率更高。
3:low 和 high 的更新。low = mid + 1,high = mid - 1。

二分查詢時間複雜度分析

二分查詢每次查詢的資料範圍都會是上一次的一般,也就是查詢資料的範圍呈下列趨勢:n/2,n/4,n/8…,n/2^k。其中,n 是陣列的長度,k是執行次數。最壞的情況,當 n/2^k = 1的時候,也就是資料被查詢到k = log2n,所以時間複雜度為:O(logn)。舉個例子,當 n 等於 2 的 32 次方的時候,大約 40 億。反過來,想在 40 億個資料中找到某個值,大約需要32次比較。

二分查詢應用侷限性

二分查詢依賴的是順序表結構,即陣列。因為二分查詢過程中需要不斷訪問不同區間的中間位置上的元素,只有陣列這種結構,隨機訪問的時間複雜度是 O(1)。如果用連結串列實現二分查詢的話,每次都要遍歷不同區間的元素才能確定中間位置上的元素,時間複雜度變得很高了。

二分查詢針對的是有序資料。對於頻繁插入刪除的資料,不建議使用二分查詢。因為為了保證資料的有序性,每次使用二分查詢之前都需要對資料進行排序,維護成本增加了。

資料量小的時候不適合使用二分法查詢。因為遍歷一邊陣列的時間複雜度和二分法查詢的時間複雜度相差無幾。如果,遍歷查詢的時候,資料比較的時候耗時過長,此時建議使用二分法查詢。減少比較次數,也是在提高演算法的執行效率。

如何最省記憶體實現快速查詢

如何在 100 萬個整數中查詢某個整數?記憶體限制是 100M,每個資料大小是 8 個位元組。
將資料全部獲取到記憶體中,佔用大約 80M。然後先對資料排序,再用二分法查詢。

總結

本文創作靈感來源於 極客時間 王爭老師的《資料結構與演算法之美》課程,通過課後反思以及借鑑各位學友的發言總結,現整理出自己的知識架構,以便日後溫故知新,查漏補缺。

初入演算法學習,必是步履蹣跚,一路磕磕絆絆跌跌撞撞。看不懂別慌,也別忙著總結,先讀五遍文章先,無他,唯手熟爾~
與諸君共勉

關注本人公眾號,第一時間獲取最新文章釋出,每日更新一篇技術文章。

在這裡插入圖片描述