1. 程式人生 > >資料結構學習筆記四(二分查詢)

資料結構學習筆記四(二分查詢)

一、什麼是二分查詢

       二分查詢針對的是一個有序的資料集合,每次都通過更區間的中間元素做對比,將要查詢的區間縮小為原來的一半,直到找到要查詢的元素,或者區間被縮小為0。其時間複雜度為O(logn)。

二、二分查詢應用場景的侷限性

1.二分查詢依賴的是順序表結構(即陣列)
       二分查詢需要按照下標來隨機訪問元素。二分查詢只能用在順序表來儲存的資料結構上,如果資料是通過其他資料結構儲存的,則無法使用二分查詢。
2.二分查詢針對的是有序資料


       二分查詢要求資料時有序的。如果資料沒有序,可以先排序。如果我們針對的是一組靜態資料,沒有頻繁的插入,刪除,我們可以進行一次排序,多次二分查詢。這樣排序的成本就被分攤,二分查詢的邊際成本就會比較低。但是如果資料集合有頻繁的插入和刪除操作,要使用二分查詢,在每次二分查詢前都要先進行排序。針對珍重動態資料集合,維護有序的成本很高。
       二分查詢只能用在插入,刪除不頻繁,一次排序多次查詢的場景中。針對動態變化的資料集合,二分查詢將不再適應。
3.資料量太小不適合二分查詢

       如果要處理的資料量很小,完全沒有必要使用二分查詢,順序查詢就夠了。但是有一個例外,如果資料之間的比較操作比較耗時,不管資料量大小,都推薦使用二分查詢。(比如陣列中儲存的都是長度超過300的字串,如此長的兩個字串進行比較就非常耗時,此時使用二分查詢可以減少比較次數,提高效能)
4.資料量太大也不適合二分查詢
       二分查詢需要依賴陣列這種資料結構,而陣列為了支援隨機訪問的特性,要求記憶體空間連續,對記憶體的要求比較苛刻。如果太大的資料用陣列儲存就比較吃力了(開闢不出連續空間),也就不能用二分查找了。

三、二分查詢的適用範圍

       凡是用二分查詢能解決的,絕大部分我們更傾向於用散列表或者二叉查詢數。實際上,求“值等於給定值”的二分查詢確實不怎麼會被用到,二分查詢更適合用在“近似”查詢問題,在這類問題上,二分查詢的優勢明顯。而用其他資料結構,比如散列表、二叉樹就比較難實現了。

四、二叉樹的變種

1.查詢第一個值等於給定值的元素

//1.查詢第一個值等於給定值的元素
	public int binarySearch1(int[] a,int n,int value){
		int low=0;
		int high=n-1;
		while(low<=high){
			int mid=low+((high-low)>>1);
			if(a[mid]<value){
				low=mid+1;
			}else if(a[mid]>value){
				high=mid-1;
			}else{
				if(mid==0 || a[mid-1]!=value)    //如果mid==0,那它已經是陣列的第一個元素了,一定是我們要找的
					return mid;                  //如果mid不等於0,a[mid-1]不等於value,那a[mid]就是我們要找的
				else
					high=mid-1;
			}
		}
		return -1;
	}

2.查詢最後一個值等於給定值的元素

//2.查詢最後一個值等於給定值的元素
	public int binarySearch2(int[] a,int n,int value){
		int low=0;
		int high=n-1;
		while(low<=high){
			int mid=low+((high-low)>>1);
			if(a[mid]<value){
				low=mid+1;
			}else if(a[mid]>value){
				high=mid-1;
			}else{
				if(mid==n-1 || a[mid+1]!=value)
					return mid;
				else
					low=mid+1;
			}
		}
		return -1;
	}

3.查詢第一個大於等於給定值的元素

//3.查詢第一個大於等於給定值的元素
	public int binarySearch3(int[] a,int n,int value){
		int low=0;
		int high=n-1;
		while(low<=high){
			int mid=low+((high-low)>>1);
			if(a[mid]>=value){
				if(mid==0 || a[mid-1]<value)
					return mid;
				else
					high=mid-1;
			}else{
				low=mid+1;
			}
		}
		return -1;
	}

4.查詢最後一個小於等於給定值的元素

//4.查詢最後一個小於等於給定值的元素
	public int binarySearch4(int[] a,int n,int value){
		int low=0;
		int high=n-1;
		while(low<=high){
			int mid=low+((high-low)>>1);
			if(a[mid]<=value){
				if(mid==n-1 || a[mid+1]>value)
					return mid;
				else
					low=mid+1;
			}else{
				high=mid-1;
			}
		}
		return -1;
	}