数据结构和算法-线性查找-二分查找

一、二分查找简述

折半查找(Binary Search)又称为二分查找,其要求数据序列呈线性结构,也就是经过排序的数据序列。对于没有经过排序的数据序列,可以先进行排序操作,然后执行折半查找操作。它是一种效率较高的查找方法。但二分查找有一定的条件限制:要求线性表必须采用顺序存储结构,且表中元素必须按关键字有序(升序或降序均可)。

二、二分查找分析

折半查找的基本思路是:

在有序表中,取中间的记录作为比较对象

(1)如果要查找的值等于中间索引对应的值,则查找成功。

(2)若中间索引对应的值大于要查找的值,则在中间索引的前半部分继续查找。

(3)若中间索引对应的值小于要查找的值,则在中间索引的后半部分继续查找。

(4)不断重述上述查找过程,直到查找成功,或有序表中没有所要查找的值,查找失败。

具体操作过程如下:

现在我们有一个有序的整型数组listData,然后设置两个变量,一个是low,指向数组第1个索引的位置,即:low=0;另一个是high,指向数组最后一个索引的位置,即:high=listData.length-1。

设要查找的值为value。当low≤high时,反复执行以下步骤:

(1)计算中间索引的位置mid,mid=(low+high)/2。

(2)将待查找的值value和listData[middle]进行比较。

​ ① 若listData[middle] == value,查找成功,middle所指元素即为要查找的元素。

​ ② 若listData[middle] > value,说明若存在要查找的值,该值一定在查找有序数组的前半部分。修改查找范围的上界:high=middle-1,转(1)。

​ ③ 若listData[middle] < value,说明若存在要查找的值,该值一定在查找有序数组的后半部分。修改查找范围的下界:low=middle+1,转(1)。

重复以上过程,当low>high时,表示查找失败。

接下来我们用图文的形式分下查找的过程:

现在有一组有序的整型数据为{2, 12, 15, 23, 25, 28, 39, 40,46,66}

若要查找value=39的记录,则折半查找过程如下。

(1)初始时

low=0;

high=9;

mid=(low+high)/2, middle=4;

listData[middle]=25;
 

(2)比较listData[middle]和value,由于listData[middle] < 46,下一步到后半部分查找,于是

low=middle+1,low=5;

high依旧为9, high=9;

mid=(low+high)/2, middle=7;

listData[middle]=40;
 

(3)比较listData[middle]和value,由于listData[middle] > 39,下一步到前半部分查找,于是

low依旧为5, low=5;

high=middle-1, high=6;

mid=(low+high)/2, middle=5;

listData[middle]=28;
 

(4)比较listData[middle]和value,由于listData[middle] < 39,下一步到后半部分查找,于是

low=middle+1,low=6;
high依旧为6, high=6;
mid=(low+high)/2,middle=6;
listData[middle]=39;
 

(5)比较listData[middle]和value,由于listData[middle] == 39,查找成功,返回索引,结束。

三、二分查找的实现

package com.joshua317;

import java.util.Arrays;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        /*
        System.out.println("折半查找算法实例");
        System.out.println("请输入十个有序的整型数据");

        int[] listData = new int[10];
        Scanner scanner = new Scanner(System.in);
        // 接收数据
        for (int i = 0; i < listData.length; i++) {
            listData[i] = scanner.nextInt();
        }

        // 打印所有数组元素
        System.out.print("输入的数据为:");
        for (int i = 0; i < listData.length; i++) {
            System.out.print(listData[i] + ",");
        }
        System.out.println();
        System.out.println("请输入要查找的数据");
        int value = scanner.nextInt();
         */
        int[] listData = {2, 12, 15, 23, 25, 28, 39, 40,46,66};
        int value = 39;

        int index = binarySearch(listData, value);
        if (index != -1) {
            System.out.println("在第" + (index+1) + "个位置,数据:" + listData[index]);
        } else {
            System.out.println("数据未找到");
        }

    }

    public static int binarySearch(int[] listData, int value)
    {
        int low, middle, high;
        low = 0;
        high = listData.length - 1;
        while (low <= high) {
            middle = (low + high) / 2;
            System.out.printf("low=%d,high=%d,middle=%d,listData[middle]=%d", low, high, middle, listData[middle]);
            System.out.println();
            if (listData[middle] == value) {
                return middle;
            } else if (listData[middle] > value) {
                high = middle - 1;
            } else if (listData[middle] < value) {
                low = middle + 1;
            }
        }

        return -1;
    }
}

 

四、最后

折半查找的优点是比较次数较顺序查找要少,查找速度较快,执行效率较高。缺点是表的存储结构只能为顺序存储,不能为链式存储,且表中元素必须是有序的。折半查找成功时的平均查找长度log2(n+1)-1,它的时间复杂度为O(log2n)

 

原文地址:https://www.cnblogs.com/joshua317/p/15264424.html