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


    一、二分查找简述

    折半查找(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)

     

  • 相关阅读:
    Debian下修改/etc/fstab出错致系统无法启动修正
    三种管理方法[书摘]
    Windows Phone & Windows 8 Push Notification from Windows Azure
    Windows Phone 8 如何在内存与硬件受限的设备上开发
    Windows Phone 8 获取与监听网络连接状态
    Windows Phone 处理 MessageBox导致的应用异常退出以及使用代码方式退出应用
    Windows store 应用调用 SharePoint Service
    嵌入式成长轨迹61 【智能家居项目】【ARM 飞凌ok6410】【在虚拟机Ubuntu下NFS网络文件系统建立】
    嵌入式成长轨迹65 【智能家居项目】【ARM 飞凌ok6410】【飞凌开发板——SD卡一键烧写】
    嵌入式成长轨迹63 【智能家居项目】【ARM 飞凌ok6410】【ARM QT 移植环境搭建问题集锦】
  • 原文地址:https://www.cnblogs.com/joshua317/p/15264424.html
Copyright © 2020-2023  润新知