二分查詢

沙漠行者發表於2019-10-17
#include <iostream>
using namespace std;

/**
* 二分查詢之一: 可以找到連續重複出現的第一個出現的元素
*/
int binarySearch(int a[], int n, int x){
	int l = 0, h = n-1;
	int m;

	while(l <= h){
		m = (l+h)/2;
		if(x <= a[m]) h = m-1;	//如果相同,仍然向前走
		else l = m+1;			//否則向後走
	}

	//如果查詢的元素沒有連續出現,則取更大的指標l指向的元素
	if(l<n && a[l] == x){
		return l;
	}
	return -1;
}

/**
* 二分查詢之二: 相等即返回,不確定返回重複元素的第幾個
*/
int binarySearch2(int a[], int n, int x){
	int l=0,h=n-1;
	int m=0;
	while(l<=h){
		m = (l+h)/2;
		if(x == a[m]) return m;
		else if(x > a[m]) l = m+1;
		else h = m-1;
	}
	return -1;
}

/**
* 旋轉陣列中尋找指定的元素。
* 主要是根據中點m來判斷兩種不同的情況,然後再細分。
* 注意迴圈結束條件,以及l和h的更新。
*/
int searchRotateArray(int a[], int n, int x){
	int l = 0;
	int h = n-1;

	if(a == NULL) return -1;
	while(l+1 != h){	//當l的下一個位置就是h的時候就要結束

		int m = (l+h)/2;
		if(a[m] == x) return m;	//找到
		else if(a[m] >= a[l]){	//m落在左半部分
			if(x > a[m]) l = m;
			else{
				if(x > a[l]) h = m;
				else l = m;
			}
		}
		else{					//m落在又半部分
			if(x < a[m]) h = m;
			else{
				if(x < a[h]) l = m;
				else h = m;
			}
		}
	}
	return (a[l] == x)?l:-1;	//判斷是否找到
}

int main(){
	int a[] = {0,1,2,3,4,4,4,5,8,9,10,11,12};
	int b[] = {1};
	int c[] = {9,10,11,12,2,3,4,4,5,6,7,8};
	int d[] = {1,1,1,1,0,0,1};
	
	cout<<binarySearch(a,13,2)<<endl;
	cout<<binarySearch2(b,1,1)<<endl;
	cout<<searchRotateArray(c,12,6)<<endl;;
	cout<<searchRotateArray(c,12,4)<<endl;
	cout<<searchRotateArray(a,13,2)<<endl;
	cout<<searchRotateArray(d,7,0)<<endl;
	cout<<searchRotateArray(c,7,-1)<<endl;
	cout<<searchRotateArray(d,7,3)<<endl;
	return 0;
}

相關文章