专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

算法——查找算法

1、顺序查找:

定义:

顺序查找(Sequential Search) 又叫线性查找,是最基本的查找技术,它的查找过程是:从表中第一个(或最后一个)记录开始,逐个进行记录的关键字和给定值比较,若某个记录的关键字和给定值相等,则查找成功,找到所查的记录;如果直到最后一个(或第一个)记录,其关键字和给定值比较都不等时,则表中没有所查的记录,查找不成功。

代码:

import java.util.Scanner;

import org.junit.jupiter.api.Test;

/**
 * 顺序查找
 * @author wydream
 *
 */

public class SequelSearch {

    public int search(int[] arr,int num) {
        if(arr.length==0) {
            return -1;
        }
        for(int i=0;i<arr.length;i++) {
            if(arr[i]==num) {
                return i;
            }
        }
        return -1;
    }

    @Test
    public void test() {
        int[] arr={4,6,2,8,1,9,0,3};
        Scanner input=new Scanner(System.in);
        System.out.println("请输入你要查找的数:");
        int num=input.nextInt();
        int result=search(arr,num);
        if(result==-1){
            System.out.println("你输入的数不存在与数组中");
        }
        else {
            System.out.println("你输入的数字存在,在数组中的位置是第:"+(result+1)+"个");
        }

    }
}

  

2、折半查找(二分查找)

定义:

折半查找(Binary Search) 技术,又称为:二分查找。它的前提是线性表中的记录必须是关键码有序(通常从小到大有序),线性表必须采用顺序存储。折半查找的基本思想是:在有序表中,取中间记录作为比较对象,若给定值与中间记录的关键字相等,则查找成功;若给定值小于中间记录的关键字,则在中间记录的左半区继续查找;若给定值大于中间记录的关键字,则在中间记录的右半区继续查找。不断重复上述过程,直到查找成功,或所查找区域无记录,查找失败为止

代码:

import org.junit.jupiter.api.Test;

/**
 * 二分查找
 * 1.循环实现
 * 2.递归实现
 * @author wydream
 *
 */

public class BinarySearch {

    //1.循环实现二分查找
    public int rank(int[] arr,int num) {
        int start=0;
        int end=arr.length;
        int mid=(start+end)/2;//中间数的下标
        while(start<=end) {//退出循环的条件  若一直没找到这个数,则会退出循环
            if(arr[mid]==num)
                return mid;
            else if(arr[mid]>num) {
                end=mid-1;
            }else {
                start=mid+1;
            }
            mid=(start+end)/2;
        }
        return -1;
    }

    //2.递归实现二分查找
    public int recursion(int[] arr,int num,int start,int end) {
        int mid=(start+end)/2;
        if(start==end&&arr[mid]!=num) {
            return -1;
        }
        if(arr[mid]==num) {
            return mid;
        }else {
            if(arr[mid]>num) {
                end=mid-1;
                return recursion(arr,num,start,end);
            }else{
                start=mid+1;
                return recursion(arr,num,start,end);
            }
        }

    }

    //测试
    @Test
    public void testRank() {
        int[] arr= {2,3,6,9,13,18,20,22,24,29,30,45,67,88};
        int result=rank(arr,2);
        if(result==-1) {
            System.out.println("你要查找的数字不在该数组中");
        }else {
            System.out.println("你查找的数字在数组的第"+(result+1)+"位");
        }
    }

    @Test
    public void testRecursion() {
        int[] arr= {2,3,6,9,13,18,20,22,24,29,30,45,67,88};
        int result=recursion(arr,20,0,arr.length-1);
        if(result==-1) {
            System.out.println("你要查找的数字不在该数组中");
        }else {
            System.out.println("你查找的数字在数组的第"+(result+1)+"位");
        }
    }

}

  

3、插值查找

定义:

插值查找(Interpolation Search)是根据要查找的关键字key与查找表中最大最小记录的关键字比较后的查找方法,其核心就在于插值的计算公式。插值计算公式:mid=start+(key-a[start])/(arr[end]-arr[start])*(end-start);

代码(递归和非递归两种方法实现):

import org.junit.jupiter.api.Test;

/**
 *  插值查找(Interpolation Search)是根据要查找的关键字key与查找表中最大最小记录的关键字比较后的查找方法,其核心就在于插值的计算公式
 *  插值计算公式:mid=start+(key-a[start])/(arr[end]-arr[start])*(end-start);
 * @author wydream
 *
 */

public class InsertValueSearch {

    //递归实现插值查找
    public int recursionBinarySearch(int[] arr,int key,int start,int end) {
        //当查找的值小于数组最小值,或者大于数组最大值,或者start>end时查找结束
        if(key<arr[start]||key>arr[end]||start>end) {
            return -1;
        }
        if(arr[start]==key) {
            return start;
        }
        if(arr[end]==key) {
            return end;
        }
        int mid = start+(end-start)*((key-arr[start])/(arr[end]-arr[start]));
        if(arr[mid]>key) {
            //说明key在前半部分
            return recursionBinarySearch(arr,key,start,mid-1);
        }
        else if(arr[mid]<key) {
            //说明key在后半部分
            return recursionBinarySearch(arr,key,mid+1,end);
        }else {
            return mid;
        }
    }

    //非递归实现插值查找
    public int commonBinarySearch(int[] arr,int key) {
        int start=0;
        int end=arr.length-1;
        if(key<arr[start]||key>arr[end]) {
            return -1;
        }
        int mid = start+(end-start)*((key-arr[start])/(arr[end]-arr[start]));
        while(start<=end) {
            if(arr[mid]==key) {
                return mid;
            }else if(arr[mid]>key) {//说明查找的值在mid的前面
                end=mid-1;
            }else {//说明查找的值在mid的后面
                start=mid+1;
            }
            mid=start+(end-start)*((key-arr[start])/(arr[end]-arr[start]));
        }
        return -1;
    }

    //递归测试
    @Test
    public void testRecursion() {
        int[] arr= {1,2,4,5,6,7,8,9};
        int result=recursionBinarySearch(arr,1,0,arr.length-1);
        if(result==-1) {
            System.out.println("你要查找的数不在该数组中");
        }else {
            System.out.println("你要查找的数在数组的第"+(result+1)+"个位置");
        }

    }

    //非递归测试
    @Test
    public void testCommon() {
        int[] arr= {1,2,4,5,6,7,8,9};
        int result=commonBinarySearch(arr,1);
        if(result==-1) {
            System.out.println("你要查找的数不在该数组中");
        }else {
            System.out.println("你要查找的数在数组的第"+(result+1)+"个位置");
        }
    }

}

  

4、斐波那契查找

定义:

1、斐波那契实在二分查找基础上,用斐波那契数列来进行分割
2、在斐波那契数列上找一个略大于查找元素表个数的值f(n)
3、将查找元素表个数扩充到f(n) 如果要补充元素用最后一个元素补充
4、完成后对f(n)个元素进行斐波那契分割,即分割成 前面f(n-1)个元素,后面f(n-2)个元素
5、对要查找元素的那个部分进行递归
6、就平均性能而言 优于折半查找 但是若一直在左边长半区查找则低于折半查找

代码:

import java.util.Arrays;

import org.junit.jupiter.api.Test;

/*
 *----- 斐波那契查找------
 * 1.斐波那契实在二分查找基础上,用斐波那契数列来进行分割
 * 2.在斐波那契数列上找一个略大于查找元素表个数的值f(n)
 * 3.将查找元素表个数扩充到f(n) 如果要补充元素用最后一个元素补充
 * 4.完成后对f(n)个元素进行斐波那契分割,即分割成 前面f(n-1)个元素,后面f(n-2)个元素
 * 5.对要查找元素的那个部分进行递归 
 * 6.就平均性能而言 优于折半查找 但是若一直在左边长半区查找则低于折半查找
 * */

public class FibonacciSearch {

    private static int maxsize=20;

    //生成斐波那契数列
    public int[] fibonaqie() {
        int[] f=new int[maxsize];
        f[0]=1;
        f[1]=1;
        for(int i=2;i<maxsize;i++) {
            f[i]=f[i-1]+f[i-2];
        }
        return f;
    }

    //查找
    public int search(int[] arr,int key) {
        int low=0;
        int high=arr.length-1;
        int k=0;//斐波那契分割数值下标
        int mid=0;
        int f[]=fibonaqie();
        //获得斐波那契分割数值下标
        while(high>f[k]-1) { //int [] a= {1,3,5,7,9,11,12};  6
            k++;
        }
        //利用Java工具类Arrays 构造新数组并指向 数组 arr[]
        int[] temp=Arrays.copyOf(arr, f[k]);
        //对新构造的数组进行 元素补充
        for(int i=high+1;i<temp.length;i++) {
            temp[i]=arr[high];
        }
        while(low<=high) {
            //由于前面部分有f[k-1]个元素
            mid=low+f[k-1]-1;
            if(key<temp[mid]) {
                high=mid-1;
                /**
                 * 
                    *全部元素=前部元素+后部元素
                             * f[k]=f[k-1]+f[k-2]
                             * 因为前部有f[k-1]个元素,所以可以继续拆分f[k-1]=f[k-2]+f[k-3]
                             * 即在f[k-1]的前部继续查找 所以k--
                             * 即下次循环 mid=f[k-1-1]-1
                * */
                k--;
            }else if(key>temp[mid]) {//关键字大于切个位置元素 则查找后半部分
                low=mid+1;
                /***
                 * 全部元素=前部元素+后部元素
                 * f[k]=f[k-1]+f[k-2]
                            * 因为后部有f[k-2]个元素,所以可以继续拆分f[k-2]=f[k-3]+f[k-4]
                            * 即在f[k-2]的前部继续查找 所以k-=2
                            * 即下次循环 mid=f[k-1-2]-1
                 */
                k-=2;
            }else {
                if(mid<=high) {
                    return mid;
                }else {
                    return high;
                }
            }
        }
        return -1;
    }

    @Test
    public void test() {
        int [] a= {1,3,5,7,9,11,12};
            int i=search(a, 5);
            System.out.println("5在:"+(i+1));
            int j=search(a, 12);
            System.out.println("12在:"+(j+1));
    }

}

文章永久链接:https://tech.souyunku.com/36290

未经允许不得转载:搜云库技术团队 » 算法——查找算法

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们