目录

线性查找法介绍

实现线性查找法

使用泛型

使用自定义类测试算法

循环不变量

简单的复杂度分析

常见的时间复杂度

测试算法性能


线性查找法介绍

线性查找法是一个非常简单的算法,比如说现在有一打试卷在,每个试卷都有自己的一个编号,在这一沓试卷当中找到属于自己的那一张试卷。一个一个去寻找自己的目标元素,就是线性查找法,例如:

实现线性查找法

对于以上算法返回的是一个int,也就是所查找的目标元素所对应的索引值,此时这个算法需要两个参数,第一个是数组,第二个是目标元素 。

public class LinearSearch {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 = {24,18,12,9,16,66,32};LinearSearch ls = new LinearSearch();int res = ls.search(data,16);System.out.println(res);int res2 = ls.search(data,666);System.out.println(res2);}
}

仔细看LinearSearch是一个动词,创建一个动词的类对象看样子有点奇怪,所以将search函数设置为静态,相应的在调用search这个方法的时候。就不需要再次实例化LinearSearch了,可以接调用linear search这个类的名称,从而调用函数,这才是一个更加自然的设计方式。我们没有必要去创建linear search这个类。我们直接调用LinearSearch中的静态方法Search方法来查找。数组中target的索引。

我们这个累并不希望用户去创建linear search这样的一个对象,那怎么做才能阻止呢?可以将linear search的构造函数设置成私有的。

public class LinearSearch {public 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;}public static void main(String[] args) {int[] data = {24,18,12,9,16,66,32};int res = LinearSearch.search(data,16);System.out.println(res);int res2 = LinearSearch.search(data,666);System.out.println(res2);}
}

使用泛型

现在对于这个算法来讲,它使用的是一个int类型数组,而目标也是int类型,而现实中要查找的类型。可能是千奇百怪的,有可能是字符串,也可能是字符,也有可能是用户自己设置的类,这个时候就需要使用到泛型。

此时最好将search方法设置为泛型方法,此时数组data设置为e,Target的类型也为e,此时参数的类型不再固定为int型,用户可以根据自己的代码来选择合适的类型。(泛型只能接受类对象,而不能接受基本数据类型,当时用泛型的时候,如果我们想传入的类型是基本数据类型的时候,此时就需要把它转化为对应的包装类即可)

public class LinearSearch {public 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;}public static void main(String[] args) {Integer[] data = {24,18,12,9,16,66,32};int res = LinearSearch.search(data,16);System.out.println(res);int res2 = LinearSearch.search(data,666);System.out.println(res2);}
}

注意,对于类之间的判断需要用equals方法。

对于不同的历来讲方法内部实现的逻辑有可能是不同的,对于一般的数据类型,equals方法足以应对,但是如果使用自己定义的类的话,就需要注意在自己定义的类当中将equals方法。的逻辑实现出来,这个任务不是线性查找法该实现的,而是这个类的设计者去实现的。

使用自定义类测试算法

自定义一个student类,并且去完善equals方法。

在主方法当中定义一个student类型的数组,然后再定义一个student类型来确定要查找的元素。

        Student[] students = {new Student("alice"),new Student("bobo"),new Student("xiaoming")};Student target = new Student("bobo");int res3 = LinearSearch.search(students,target);System.out.println(res3);

返回结果是-1,这是为什么呢?因为equals方法默认比较的是两个类对象的地址,而在我们的逻辑中,想要比较的是字符串,所以这个逻辑就需要我们自己去自定义equals函数,我们需要重写equals方法,所以equals方法中的参数类型需要与父类Object保持一致。

import java.util.Objects;public class Student {private String name;public Student(String name) {this.name = name;}@Overridepublic boolean equals(Object student) {/*强制转换有可能出现异常,因此需要做出判断*/if (this == student)//比较当前类对象与传入的参数是否一致,如果一致,则不需要进行强制类型转换了,直接为truereturn true;if (student == null)//如果传入的对象为空的话,则直接为false即可return false;/*如果当前的类对象与传入参数的类对象不属于同一个类的话,则直接为false,也不需要强制转换了(之所以重写equals方法需要强制转换,是因为它的参数必须为类型Object,以此来涵盖所有可能传入的参数类型,而如果具体传来的参数类型与。挣钱类对象不同的话,则这两个对象肯定是不同的)*/if (this.getClass() != student.getClass())return false;Student another = (Student) student;return this.name.equals(another.name);//写比较逻辑}}

如果我们想要比较的逻辑是比较学号或者比较的逻辑是姓名忽略大小写的,都可以对student类当中的equals方法进行一个修改。

循环不变量

循环是程序设计中一种非常重要的构建逻辑的方式,实际上几乎所有的算法都有循环这个概念,我们总会使用循环来用算法进行求解。

在每一轮循环开始的时候,这个条件本身是不变的,这就是循环不变量。经过这个循环体之后,要么循环结束了,已经return i了,要么循环继续,如果循环继续的话,在下一轮循环中,如果依旧满足循环不变量的话,则继续依靠循环体维持循环不变量

简单的复杂度分析

简单的来说,我们之所以要对算法做复杂度分析,是因为我们需要表示算法的性能,我们后续都会看到对于这样的一个任务,我们会有不同的算法能够完成这个任务,那对于不同的算法来说,他们的时间性能是不是有差异呢?当然,我们可以具体的用一个任务或者是具体测试用例对不同的算法都运行一下实际的去比较一下它的性能差异,但是这样的比较结果很多时候是有局限性的,因为严格来讲,你需要保证运行不同的算法的这个计算机他们的性能是完全一致的,甚至他们使用的系统,系统当时的状态都是完全一致的,这个是很难一致的,与此同时测试的结果呢也会和我们具体的测试用例是怎样的相关,更重要的是这样做,我们必须先把这个算法实体的实现出来,才能看到它的性能,但是很多时候呢我们有这个算法思想之后,我们希望可不可能通过这个算法的思想大致评出这个算法的性能是实力是不是能够满足我们真正的需求,然后再来决定是否要去实现它,这些原因都使得我们需要有一套工具能够非常抽象的从数学的层面就去判断一个算法它的性能是怎么样的,那么为了解决这个问题,就产生了复杂度分析这样一个概念。

我们不去仔细的分析,实行这一轮循环,对这n个元素操作,每一次在这个元素的操作上需要多少指令,我们只需要知道我们整个这个算法它的性能和这个data数目n的大小,也就是这个数据规模成立的正比关系就好了,那么这样的一个算法,计算机科学家就把它记作叫做大O(n)级别的算法,在这里这个大O(n)的符号它有一个非常严谨的数学定义。

常见的时间复杂度

我们看一个学算法的复杂度,不能简单的数循环个数,比如这个循环它也是一层循环,但它并不是On级别,因为他不是每次-1-1到0,而是每次除以2到0,所以他直到0的速度非常快,是logN的级别。

以下算法只是循环条件不同,循环具体执行的轮数是不同的

空间复杂度,它的表示符号其实和这个时间复杂度完全是同理的,也就是他对于我们写这一算法来说,我们需要开辟的额外的空间的大小和数据规模n之间的关系是怎样的,那么对于在这一章我们讲的这个非常简单的线性查找法来说,可能可以想象一下,我们为了完成这个计算,其实没有开任何额外的空间,因此这个算法的空间复杂度的就是O(1)这个级别的。

不过通常来讲在我们算法设计的过程中不太强调空间复杂度,更强调时间复杂度,这是因为对于现代计算机来说,空间其实是越来越不值钱的,我们的计算机内存越来越大,硬盘容量越来越多,但相较而言时间是更值钱的,所以我们实际在学习算法的过程中会更加看重时间复杂度,也正是因为如此的多算法设计的核心思想,其实它的本质呢是用空间换时间,也就是我们能不能先存点儿什么东西来加快我们整个算法的运行,那么实际上很多数据结构的原理呢也是如此。

测试算法性能

生成指定长度数组

public class ArrayGenerator {public ArrayGenerator() {}/*根据用户传来n的大小来创建长度为n的数组*/public static Integer[] generateOrderedArray(int n){Integer[] arr = new Integer[n];for (int i = 0;i<n;i++){arr[i] = i;}return arr;}
}

性能测试:

public class LinearSearch {public 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;}public static void main(String[] args) {int n = 1000000;Integer[] data = ArrayGenerator.generateOrderedArray(n);long starttime = System.nanoTime();//毫秒级别LinearSearch.search(data,n);//模拟最坏情况long endtime = System.nanoTime();double time = (endtime - starttime)/1000000000.0;System.out.println(time+"s");}
}

算法与数据结构(第一周)——线性查找法相关推荐

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

    算法与数据结构体系 - 线性查找 什么是算法 线性查找法 基础创建 修改1:私有化 修改2:泛型 提升:自定义Student类测试算法 复杂度分析:表示算法的性能 常见算法的复杂度 测试算法性能 什么 ...

  2. 算法与数据结构基础<一>----线性查找法

    开篇: 对于数据结构及算法的学习在17年时就已经在博客中开了专栏: 但是!!!感觉学得有点零散,有c版本的,也有java版本的,没成体系,当然其效果也并没达到自己满意的效果,基于此,这里准备重新开个专 ...

  3. 大话西游之王道考研数据结构第一讲---线性表的顺序表示

    大话西游之王道考研数据结构第一讲---线性表的顺序表示 写在前面的话 王道考研数据结构是一本非常好的书,本系列所有的内容是按照其书进行讲述的,所以您可以以那本书作为主要内容,这个做参考. 大学时候,在 ...

  4. 腾讯广告算法大赛 | 复赛第一周周冠军心得分享

    腾讯广告算法大赛 | 复赛第一周周冠军心得分享 腾讯广告算法大赛复赛第一周周冠军揭晓, 熟悉的队伍,熟悉的配方! 没错,依然是你们熟悉的葛文强团队! 今天,他们将对FFM方法进行详细介绍. 小板凳儿排 ...

  5. 算法与数据结构(一):线性表(C++实现)

    文章目录 算法与数据结构(一):线性表(C++实现) 头文件定义线性表类的成员变量和成员函数 头文件类成员函数的实现 主函数 参考:算法分析与设计(C++描述) 石志国.刘冀伟.姚亦飞编著 算法与数据 ...

  6. 线性查找法java代码_Java线性查找和二分查找

    Java线性查找和二分查找. 一 线性查找 定义:在一列给定的值中进行搜索,从一端开始逐一检查每个元素,直到找到所需元素的过程. 线性查找又称为顺序查找.如果查找池是某种类型的一个表,比如一个数组,简 ...

  7. 小饶学编程之JAVA SE第一部分——二分查找法

    二分查找法 一.算法描述 二.算法原理 三.算法实现 四.总结 一.算法描述 二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法.但是,折半查找要求线性表必须采用顺序存储结 ...

  8. 【算法与数据结构实战】线性表操作-实现A并B,结果放入A中

    //数据结构与算法基础题1:线性表操作,实现A并B,结果放入A中#include "stdafx.h" #include <iostream> #include < ...

  9. 数据结构与算法Python版-第一周测验

    1单选(2分) 以下关于基于有穷观点的能行方法说法错误的是: A. 指令执行在有限步骤后终止 B. 由有限数量的任意指令构成 C. 指令每次执行都得到唯一的结果 D. 原则上可以由人单独采用纸笔完成 ...

最新文章

  1. java事件处理模型_从零开始理解JAVA事件处理机制(3)
  2. Qt rviz 机器人
  3. BIOS INT 10中断功能
  4. Cocos2d-x 寻路算法解析(二): 离目的地的距离优先
  5. Pytest高级进阶之Fixture
  6. warning no newline at the end of file
  7. UPS改造及终端流量监控系统
  8. Python(pycharm)在windows下路径 ( ' / ' 与' \ ' )的问题
  9. 步步为营-17-FileStream-文件加密/解密
  10. Elasticsearch 实战1:ES 项目实战(一)Java 集成 Spring Data Elasticsearch(一):简介及环境搭建
  11. 贝叶斯定理到贝叶斯滤波器
  12. python请求库_如何使用Python请求库发出post请求?
  13. *SQL Server系统表的应用
  14. Qualcomm 3D音频插件学习
  15. 三国杀服务器维护中进不去,三国杀网页版打不开该怎么解决?
  16. 欠采样临界采样matlab,信号临界采样、过采样、欠采样实验报告.doc
  17. 用Python批量生成字幕图片用于视频剪辑
  18. 基于JavaEE的酒店客房管理系统
  19. python中减号怎么打_python减号
  20. Web端兼容性测试--浏览器/平台/分辨率

热门文章

  1. 关于NBA所有数据的爬虫(rvest)
  2. 童文、李烨:6G的9大挑战
  3. 一次学神and农夫and“i春秋”的心理交锋
  4. cad自动填写页码lisp,CAD图纸页码的自动生成-农夫也玩CAD
  5. 一篇文章教你如何写出【✨无法维护✨】的代码?
  6. Flex是什么? flex和flash是什么关系?
  7. electron-updater更新遇到的问题 The URL protocol of the current origin (‘app://.‘) is not supported
  8. unicode 和 GB2312 编码对应表
  9. js汉字转换拼音(网上找的js库)
  10. Tornado之模板