栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java数据结构与算法——线性查找 & 二分查找 & 插值查找

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java数据结构与算法——线性查找 & 二分查找 & 插值查找

1.线性查找

有一个数列: {1,8, 10, 89, 1000, 1234} ,判断数列中是否包含此名称【顺序查找】 要求: 如果找到了,就提示找到,并给出下标值。

package com.szh.search;


public class SeqSearch {

    //这里我们实现的线性查找是找到一个满足条件的值,就返回
    private static int seqSearch(int[] arr, int value) {
        //线性查找是逐一比对,发现有相同值,就返回下标
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == value) {
                return i;
            }
        }
        return -1;
    }

    public static void main(String[] args) {
        int[] arr = { 1, 9, 11, -1, 34, 89 }; //无序数组
        int index = seqSearch(arr, 34);
        if (index == -1) {
            System.out.println("没有找到这个值");
        } else {
            System.out.println("找到了这个值,对应下标为:" + index);
        }
    }
}


2.二分查找

二分查找:请对一个有序数组进行二分查找 {1,8, 10, 89, 1000, 1234} ,输入一个数看看该数组是否存在此数,并且求出下标,如果没有就提示"没有这个数"。

课后思考题: {1,8, 10, 89, 1000, 1000,1234} 当一个有序数组中,有多个相同的数值时,如何将所有的数值都查找到,比如这里的 1000。

package com.szh.search;

import java.util.ArrayList;
import java.util.List;


public class BinarySearch {

    
    private static int binarySearch(int[] arr, int left, int right, int findVal) {
        //当 left > right 时,说明递归整个数组,但是没有找到,此时直接返回-1
        if (left > right) {
            return -1;
        }

        int mid = (left + right) / 2;
        int midVal = arr[mid];
        if (findVal > midVal) {
            return binarySearch(arr, mid + 1, right , findVal);
        } else if (findVal < midVal) {
            return binarySearch(arr, left, mid - 1, findVal);
        } else {
            return mid;
        }
    }

    
    private static List binarySearch2(int[] arr, int left, int right, int findVal) {
        //当 left > right 时,说明递归整个数组,但是没有找到,此时直接返回空list
        if (left > right) {
            return new ArrayList<>();
        }

        int mid = (left + right) / 2;
        int midVal = arr[mid];
        if (findVal > midVal) {
            return binarySearch2(arr, mid + 1, right , findVal);
        } else if (findVal < midVal) {
            return binarySearch2(arr, left, mid - 1, findVal);
        } else {
            List resIndexList = new ArrayList<>();
            //向 mid 索引值的左边扫描,将所有满足 1000 的元素的下标,加入到集合ArrayList
            int temp = mid - 1;
            while (true) {
                //索引小于0表示已到达数组最左边,arr[temp] != findVal表示找到不等于findVal的就可以退出了
                if (temp < 0 || arr[temp] != findVal) {
                    break;
                }
                resIndexList.add(temp); //找到了就加入list中
                temp--; //因为是向左查找,所以索引值依次-1
            }
            //别忘了,还要将最先查找到的mid下标加入list中
            resIndexList.add(mid);
            //向mid 索引值的右边扫描,将所有满足 1000 的元素的下标,加入到集合ArrayList
            temp = mid + 1;
            while (true) {
                //索引大于arr.length - 1表示已到达数组最右边,arr[temp] != findVal表示找到不等于findVal的就可以退出了
                if (temp > arr.length - 1 || arr[temp] != findVal) {
                    break;
                }
                resIndexList.add(temp); //找到了就加入list中
                temp++; //因为是向右查找,所以索引值依次+1
            }
            return resIndexList;
        }
    }

    public static void main(String[] args) {
        int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 , 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
		int resIndex = binarySearch(arr, 0, arr.length - 1, 14);
		System.out.println("resIndex = " + resIndex);

        System.out.println("---------------------------------");

        int[] array = { 1, 8, 10, 89, 1000, 1000, 1000, 3333, 9527};
        List list = binarySearch2(array, 0, array.length - 1, 1000);
        System.out.println(list);
    }
}

运用二分查找算法,在n个元素的数组中查找一个数,情况最遭时,需要(log2 n)步,所以二分查找的时间复杂度是O(log2 n)。


3.插值查找

插值查找算法类似于二分查找,不同的是插值查找每次从自适应mid处开始查找。

将折半查找中的求mid 索引的公式 , low 表示左边索引left, high表示右边索引right. key 就是上面代码中的  findVal。

    改成→ 

int mid = low + (high - low) * (key - arr[low]) / (arr[high] - arr[low])  ;

对应前面的代码公式: int mid = left + (right – left) * (findVal – arr[left]) / (arr[right] – arr[left]) 

package com.szh.search;


public class InsertValueSearch {

    private static int insertValueSearch(int[] arr, int left, int right, int findVal) {
        int num = 0;
        System.out.println("插值查找的次数:" + (++num));

        //注意:findVal < arr[0]  和  findVal > arr[arr.length - 1] 必须需要
        //否则我们得到的 mid 可能越界
        if (left > right || findVal < arr[0] || findVal > arr[arr.length - 1]) {
            return -1;
        }
        //求出mid, 自适应 (插值查找的核心就是下面这行代码)
        int mid = left + (right - left) * (findVal - arr[left]) / (arr[right] - arr[left]);
        int midVal = arr[mid];
        if (findVal > midVal) { //说明应该向右边递归
            return insertValueSearch(arr, mid + 1, right, findVal);
        } else if (findVal < midVal) { //说明向左递归查找
            return insertValueSearch(arr, left, mid - 1, findVal);
        } else {
            return mid;
        }
    }

    public static void main(String[] args) {
        int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 , 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
        int resIndex = insertValueSearch(arr, 0, arr.length - 1, 14);
        System.out.println("查找元素的下标 resIndex = " + resIndex);
    }
}

插值查找注意事项:

    对于数据量较大,关键字分布比较均匀的查找表来说,采用插值查找, 速度较快。关键字分布不均匀的情况下,该方法不一定比折半查找要好。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/768337.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号