検索アルゴリズム---二分探索(再帰的方法)

二分探索

前提条件

バイナリ検索は、順序付けられた配列で検索する必要があります

小さいものから大きいものへ、または大きいものから小さいものへ

トピック

順序付けられた配列に対してバイナリ検索{1、8,10,89,1000,1234}実行し、番号を入力し
て配列がこの番号に含まれているかどうかを確認し、含まれていない場合は添え字を入力してください。そのような番号はありません」。

アイデア

今回は二分探索で再帰的思考を使用しますが、もちろん非再帰的方法もありますので、別途学習します。

1.最初に、配列の中央の添え字mid mid =(left + right)/ 2を決定します。

2.findValueをarr [mid]と比較します

findValue> arr [mid]の場合、再帰的に右に検索します

findValue <arr [mid]の場合、左に再帰的検索します

見つけた場合は、

再帰的出口(終了条件)とは何ですか

1.見つけたら、戻って終了します

2.配列全体を再帰的に実行する場合、findValueが見つからないため、再帰を終了する必要があります。左>右が終了したことを意味します。

コード

//二分查找
//@author 王
public class BinarySearch {
    
    

	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub
		int arr[] = {
    
    1,8,10,89,1000,1234};//必须是有序数组
		int resultIndex = binarySearch(arr, 0, arr.length -1, 1234);
		System.out.println(resultIndex);
	}
	/**
	 * 
	 * @param arr			数组
	 * @param left			左边索引
	 * @param right			右边索引
	 * @param findValue		需要找的数字,找到返回下标,未找到返回-1
	 * @return
	 */
	//二分查找算法
	public static int binarySearch(int[] arr,int left,int right,int findValue) {
    
    
		int mid = (left+right)/2;
		int midValue = arr[mid];
		
		if(findValue >midValue){
    
    
			//向右递归
			return binarySearch(arr, mid+1, right, findValue);
		}else if(findValue < midValue){
    
    
			//向左递归
			return binarySearch(arr, left, mid-1, findValue);
		}else{
    
    
			return mid;
		}
	}

}

問題を見つけるのは簡単です。再帰に問題があります。存在しないデータレスキューが見つかった場合は、エラーが報告されます。このエラーは、再帰が完全に原因で発生します。

Exception in thread "main" java.lang.StackOverflowError
	at 查找算法.BinarySearch.binarySearch(BinarySearch.java:27)

次に、この再帰的な終了出口作成する必要があります

改善する

//二分查找
//@author 王
public class BinarySearch {
    
    

	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub
		int arr[] = {
    
    1,8,10,89,1000,1234};//必须是有序数组
		int resultIndex = binarySearch(arr, 0, arr.length -1, 123);
		if(resultIndex != -1){
    
    
			System.out.println(resultIndex);
		}else{
    
    
			System.out.println("没有找到这个数字");
		}
	}
	/**
	 * 
	 * @param arr			数组
	 * @param left			左边索引
	 * @param right			右边索引
	 * @param findValue		需要找的数字,找到返回下标,未找到返回-1
	 * @return
	 */
	//二分查找算法
	public static int binarySearch(int[] arr,int left,int right,int findValue) {
    
    
		if(left > right){
    
    
			return -1;
		}
		int mid = (left+right)/2;
		int midValue = arr[mid];
		if(findValue >midValue){
    
    
			//向右递归
			return binarySearch(arr, mid+1, right, findValue);
		}else if(findValue < midValue){
    
    
			//向左递归
			return binarySearch(arr, left, mid-1, findValue);
		}else{
    
    
			return mid;
		}
	}

}

少し拡張してみましょう。これは、教師の放課後の演習で
もあります{1,8,10,89,1000,1000,1000,1234}順序付けられた配列に複数の同一の値がある場合、すべてを見つける方法値To、たとえば、ここでは1000です。

アイデアは前回学んだこと似ています。コレクションを使用してインデックス値を保存し、コレクションに戻ることができます。

コード

public class BinarySearch {
    
    

	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub
		int arr[] = {
    
    1,8,10,89,1000,1000,1000,1234};//必须是有序数组
		ArrayList<Integer> resultIndex = binarySearch2(arr, 0, arr.length -1, 1000);
		if(resultIndex.size() == 0){
    
    
			System.out.println("没有找到这个数字");
		}else{
    
    
			System.out.println(resultIndex);
		}
	}
    public static ArrayList<Integer> binarySearch2(int[] arr,int left,int right,int findValue) {
    
    
			if(left > right){
    
    
				return new ArrayList<Integer>();
			}
			int mid = (left+right)/2;
			int midValue = arr[mid];
			if(findValue >midValue){
    
    
				//向右递归
				return binarySearch2(arr, mid+1, right, findValue);
			}else if(findValue < midValue){
    
    
				//向左递归
				return binarySearch2(arr, left, mid-1, findValue);
			}else{
    
    
				ArrayList<Integer> list = new ArrayList<Integer>();
				int temp = mid -1;
				//向左边扫描
				while(true){
    
    
					if(temp < 0 || arr[temp] != findValue){
    
    
						//退出
						break;
					}else{
    
    
						//否则就将temp放到集合中
						list.add(temp);
						temp -= 1;//temp左移
					}
				}
				list.add(mid);
				//向右扫描
				temp = mid +1;
				while(true){
    
    
					if(temp > arr.length - 1 || arr[temp] != findValue){
    
    
						//退出
						break;
					}else{
    
    
						//否则就将temp放到集合中
						list.add(temp);
						temp += 1;//temp左移
					}
				}
				return list;
			}
		}
}

おすすめ

転載: blog.csdn.net/qq_22155255/article/details/112847063