线性查找:面对线性数据结构进行的查找算法(链表,数组)
同时,为了实现泛型,需要对类的 equals 方法进行重写
一、原理:
1.对于数组:
就是利用下标对数组进行遍历,然后直到获得目标值。
输入:数组, 目标元素
输出:目标元素所在索引;若不存在,返回 -1
2.对于链表:
利用 Node 节点的 next 指向,对 node 进行遍历,进行查找。
输入:目标元素
输出:boolean ( 是否存在该值 ),或者使用 index 记录所在顺序。
若不存在,返回 -1;
- 数组在内存中存储位置连续分布,而链表不行,所以链表无法使用 foreach 循环进行遍历
二、简单实现:
第一版
public class LinerFind {public int search(int[] data, int target){for(int i = 0;i<data.length;i++){if(data[i] == target){return i;}}return -1;}//单元测试public static void main(String[] args) {int[] data = {1,23,4,56,66,780,546};LinerFind lf = new LinerFind();int res = lf.search(data, 1);System.out.println(res);}}
// LinerFind 是一个动态词汇, 最好把 search 方法写成静态方法, 这样调用 就不需要创建对象
思考一下 Math 和 Integer.parseInt() 也没有创建对象后再进行使用,因为并不需要创建对象,只是想操作这个对象。
将 search 方法定义为 static 方法, 并将构造函数定义为 private ,这样用户就不会使用构造了。
第二版(应对不同的数据类型,避免重复)
复习一下泛型,泛型需要使用的为类对象,而不是基本数据类型,所以产生类对应的包装类。
- 泛型类型 不能适用于静态方法,使用其他类型区分,将静态方法的泛型类型和实例类型的泛型类型区分开。
// 使用泛型(java中的 map, list 等都是使用泛型类)private LinearSearch2(){}public static <T> int search(T[] data, T target){for(int i = 0;i<data.length;i++){if(data[i].equals(target)){ // 此时为两个类对象,使用 equals 不用 ==return i;}}return -1;}public static void main(String[] args) {Integer[] data = {1,23,4,56,66,780,546};int res = LinearSearch2.search(data, 1);System.out.println(res);}
作业:自己写一个类。重写 equals(),避免产生错误:
public class Student {private int age;private String name;public Student(int age, String name) {this.age = age;this.name = name;}public int getAge(){return this.age;}public String getName(){return this.name;}// 判断对象是否为空或者为统一类型// 然后再比较值判断相等@Overridepublic boolean equals(Object obj) {if (obj == null || !(obj instanceof Student)) {return false;}Student o = (Student) obj;return (this.age == o.getAge() && this.name.equals((o.getName()));}}
三、循环不变量:
四、复杂度分析:表示算法性能
通常看最差的情况:
n = data.length T = n O(n) 性能与数据规模 n 之间的关系
T1 = 1000n O(n) T2=2n^2 O(n^2)
1.常见复杂度(时间)):
while(n){n%2;n/=2;}O(logn)
长度为 n 的二进制数字 O(2^n)
长度为n的数组的所有排列 O(n!)
