算法与数据结构体系:线性查找

什么是算法

定义:一系列解决问题的,清晰,可执行的计算机指令。

  1. 有限性
  2. 确定性:无二义性
  3. 可行性
  4. 输入
  5. 输出

线性查找法

基础创建

输入: 数组,目标元素
输出: 目标元素所在的索引( 若不存在,返回 -1 )

// linear search
public class LinearSearch {
    //输入: 数组,目标元素
    public int Search(int[] data, int target){
        //遍历
        for(int i = 0; i < data.length; i ++) {
        	//如果查询到一样的内容
            if (data[i] == target) {
            	//输出:目标元素所在的索引
                return i;
            }
        }
        // 若不存在,返回 -1     
        return -1;
    }
    //测试用例
    public static void main(String[] args){
		//创建数组
        int[] data = {4, 35, 45, 42, 63, 23, 6, 77};
		// 存在的情况
		// 创建linearSearch类的对象
        LinearSearch ls = new LinearSearch();
        int res1 = ls.Search(data, 6);
        System.out.println(res1);
		// 不存在的情况
        int res2 = ls.Search(data, 7);
        System.out.println(res2);

    }
}

修改1:私有化

  1. LinearSearch是一个动词,对于动作而言,创建一个对象很奇怪,所以修改为类似Math方法的直接调用
  2. 不希望用户创建对象,将LinearSearch创建为私有的

文件1 :LinearSearch.java

public class LinearSearch {
//让它私有化 即外部不能创建对象 只能直接使用
    private LinearSearch(){}

    public static int Search(int[] data, int target){

        for(int i = 0; i < data.length; i ++) {
            if (data[i] == target) {
                return i;
            }
        }

        return -1;
    }
}

文件2:Main.java

public class Main {
    public static void main(String[] args){

        int[] data = {4, 35, 45, 42, 63, 23, 6, 77};

//        LinearSearch ls = new LinearSearch();
        int res1 = LinearSearch.Search(data, 6);
        System.out.println(res1);

        int res2 = LinearSearch.Search(data, 7);
        System.out.println(res2);

    }
}

修改2:泛型

不是只有int类型的变量,若是学生姓名的查找,换了类型之后,就会重复代码,因此需要修改 – 泛型
(目的:向Java的标准库看齐)

泛型复习

  1. 泛型只能接受类对象,不能接受基本数据类型
  2. 基本数据类型:
    boolean, byte, char, short, int, long, float, double
  3. 每个基本数据类型有对应的包装类: Boolean, Byte, Character, Short, Integer, Long, Float, Double

文件1 :LinearSearch.java

public class LinearSearch {

    private LinearSearch(){}

    public static <E> int Search(E[] data, E target){

        for(int i = 0; i < data.length; i ++) {
            // 类对象之间的判断,要使用equals方法
            if (data[i].equals(target)) {
                return i;
            }
        }

        return -1;
    }
}

文件2:Main.java

public class Main {
    public static void main(String[] args){

        Integer[] data = {4, 35, 45, 42, 63, 23, 6, 77};

        int res1 = LinearSearch.Search(data, 6);
        System.out.println(res1);

        int res2 = LinearSearch.Search(data, 7);
        System.out.println(res2);

    }
}

提升:自定义Student类测试算法

文件1 :LinearSearch.java

public class LinearSearch {

    private LinearSearch(){}

    public static <E> int Search(E[] data, E target){

        for(int i = 0; i < data.length; i ++) {
 
            if (data[i].equals(target)) {
                return i;
            }
        }

        return -1;
    }
}

文件2:Main.java

public class Main {
    public static void main(String[] args){

        Integer[] data = {4, 35, 45, 42, 63, 23, 6, 77};

        int res1 = LinearSearch.Search(data, 6);
        System.out.println(res1);

        int res2 = LinearSearch.Search(data, 7);
        System.out.println(res2);

        Student[] students = {new Student("ccq"),
                new Student("cq"),
                new Student("cc")};
        Student ccq = new Student("Ccq");
        int res3 = LinearSearch.Search(students, ccq);
        System.out.println(res3);

    }
}

文件3:Student.java

public class Student {

    private String name;

    public Student(String name){
        this.name = name;
    }

    // 设计者自己去定义什么叫两个人相等的含义
    // 将两个学生类的比较,变为学生姓名字符串的比较
    public boolean equals(Object student){
        // 地址是否是一样(即地址是否一样)
        if(this == student)
            return true;
        if(student == null)
            return false;
        // 判断类对象是否相等
        if(this.getClass() != student.getClass())
            return false;
        // 强制将Object 转化为 Student

        Student another = (Student)student;
        return this.name.toLowerCase().equals(another.name.toLowerCase());
    }
}

复杂度分析:表示算法的性能

  1. 复杂度分析通常看最差的情况
  2. 数据规模:n = data.length
  3. 算法性能:T = ?
    若 T = c1 * n + c2 → O(n)
    常数不重要
    复杂度描述的是随着数据规模N的增大,算法性能的变化趋势

常见算法的复杂度

[一定要明确n到底是谁]

O ( n ) = ( n 2 ) O(n) = (n^2) O(n)=(n2)

1. 
for(int i=0;i<data.length;i++)
	for(int j=1;j<data.length;j++)
		//获得数据对(data[i],data[j])

2. 遍历一个n*n的二位数组
for(int i=0;i<n;i++)
	for(int j=0;j<n;j++)
		//遍历到A[i][j]

O ( n ) = ( l o g n ) O(n) = (logn) O(n)=(logn)

//数字n的二进制位数
while(n){
	n % 2 // n;
	n /= 2;
}

O ( n ) = ( n ) O(n) = (\sqrt{n}) O(n)=(n )

//数字n的所有约数
for(int i=1;i*i<=n;i++){
	if(n%i==0)
		//i和n/i是n的两个约数
}

O ( n ) = ( 2 n ) O(n) = (2^n) O(n)=(2n)

长度为n的二进制数字

O ( n ) = ( n ! ) O(n) = (n!) O(n)=(n!)

长度为n的数组的所有排列

O ( 1 ) O(1) O(1) < O ( l o g n ) O(logn) O(logn) < O ( n ) O(\sqrt{n}) O(n ) < O ( n ) O(n) O(n) < O ( n l o g n ) O(nlogn) O(nlogn) < O ( n 2 ) O(n^2) O(n2) < O ( 2 n ) O(2^n) O(2n) < O ( n ! ) O(n!) O(n!)

测试算法性能

文件1 :LinearSearch.java

public class LinearSearch {

    private LinearSearch(){}

    public static <E> int Search(E[] data, E target){

        for(int i = 0; i < data.length; i ++) {
 
            if (data[i].equals(target)) {
                return i;
            }
        }

        return -1;
    }
}

文件2:Main.java

public class Main {
    public static void main(String[] args){
//        int n = 10000000;
//        Integer[] data = ArrayGenerator.generateOrderedArray(n);
//
//        long startTime = System.nanoTime(); //返回当前以纳秒对应的时间戳
//        for(int k = 0 ; k < 100 ; k ++)
//            LinearSearch.Search(data, n);
//        long endTime = System.nanoTime();
//
//        double time = (endTime - startTime) / 1000000000.0;
//        //线性查找法对于100000这个数据总共花费多少秒
//        System.out.println(time + " s");

        int [] dataSize = {1000000, 10000000};
        for(int n: dataSize) {
            Integer[] data = ArrayGenerator.generateOrderedArray(n);

            long startTime = System.nanoTime(); //返回当前以纳秒对应的时间戳
            for (int k = 0; k < 100; k++)
                LinearSearch.Search(data, n);
            long endTime = System.nanoTime();

            double time = (endTime - startTime) / 1000000000.0;
            //线性查找法对于100000这个数据总共花费多少秒
            System.out.println("n = " + n + ", 100 runs : " + time + " s");
        }
    }
}

文件3:ArrayGenerator.java

public class ArrayGenerator {

    private ArrayGenerator(){}

    public static Integer[] generateOrderedArray(int n){
        Integer[] arr = new Integer[n];
        for(int i = 0 ; i < n ; i ++){
            arr[i] = i;
        }
        return arr;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值