IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> <<从零入门数据结构>>最简单的查找算法-线性查找法 第一讲 -> 正文阅读

[数据结构与算法]<<从零入门数据结构>>最简单的查找算法-线性查找法 第一讲

1. 文章主要内容

? ? ? ?本篇博客主要讲解数据结构中最基本的线性查找方法,并通过线性查找法引出数据结构中类似循环不变量、时间复杂度等重要概念。此外,在构建算法之后会对其进行相关的测试。通读本篇博客大概需要10分钟左右的时间
? ? ? ?本篇博客的内容是基于liuyubobobo老师讲解的数据结构课程为基础,加上本人的总结和思考制作出来的,更详细的原版视频请自行搜索bobo老师数据结构(Java版本)。

2. 线性查找法

2.1 概念

? ? ? ?不去涉入更多难以懂的概念,这里用简单的例子做一个说明。假如有一个存放整型的data数组,要在这个数组中查找值为16,如下图所示:
在这里插入图片描述
? ? ? ?线性查找法意思就是从data数组的第一个数字(索引为0的地方),往后一步步寻找16在data数组中的位置(更准确的说法应该是叫索引),如果找到了,则返回16所在data数组中的索引,如果没有找到就返回-1。(注意:这里所涉及的返回值,比如-1,是这个例子特定的,并不是线性查找法通用的返回值)这样一种线性的循环遍历方法就是叫做线性查找法。

2.2 代码实现

? ? ? ?本数据结构系列的课程都会使用Java语言来编写代码,只需要掌握Java SE部分的内容即可。首先,我们new一个LinearSearch的类来承载我们写的代码,类中有一个search方法来代表我们要编写的线性查找法,如下代码所示(注意:我们这里返回的是所查找元素的索引值,所以search方法的返回类型是整型int):

public class LinearSearch {

    public static int search(int[] data, int target) {
    
    }
}

? ? ? ?接下来构造search方法内部的逻辑实现,也就是我们线性查找方法概念说的那样,循环遍历data数组,每一个data数组内的值与需要寻找的值target进行比较。如果能够找到与target相同的值,函数就返回此时的值在data数组中的索引;如果遍历完数组,依然找不到与target相等的数值,那么函数返回值就为-1

? ? ? ?我们使用for循环来构建整体的遍历,其中索引i的初始值为0,最大能够取到data.length - 1(注意:data.length为数组的长度,因为数组的索引最多只能取到data.length - 1)。另外,线性查找法的主体逻辑部分是在for循环中,让data数组中的每个值data[i]与target做相等的判断,如果if条件值为true,那么函数的返回此时的索引i。当整个数组循环遍历结束后,仍然找不到与target相等的值,那么此时函数的返回值为-1,代码如下所示:

public class LinearSearch {

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

2.3 使用泛型

? ? ? ?仔细观察我们上面的代码,其传进去的参数和返回类型都是只支持整型(int),为了让search方法支持更多的数据类型,这里使用泛型来优化代码,如下代码所示:

public class LinearSearch {

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

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

}

2.4 用自定义类来测试泛型方法

? ? ? ?为了测试我们构建的泛型方法,这里首先自定义一个Student类,其中Student类中拥有成员变量name、并且覆盖equals方法(因为自定义类的equals方法,Java并没有给我们提供,所以我们需要覆盖原object方法来自定义其equals方法),而且这里equals的逻辑是将name首先转换成小写字母,然后调用字符串String的equals方法进行相等比较(注意:String类型本身重写了Object的equals方法,所以这里不需要再对String类型的equals方法进行重写了)如下代码所示:

public class Student {

    private String name;

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

    @Override
    public boolean equals(Object student){

        if(this == student)
            return true;

        if(student == null)
            return false;

        if(this.getClass() != student.getClass())
            return false;

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

? ? ? ?接下来在LinearSearch类中创建一个main函数进行测试,自己定义了一些数据对search方法进行验证,如下代码所示:

public class LinearSearch {

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

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

   public static void main(String[] args) {
        Integer[] data = {24, 18, 12, 9, 16, 66, 32, 4};
        int res = LinearSearch.search(data, 16);
        System.out.println(res);

        int res2 = LinearSearch.search(data, 666);
        System.out.println(res2);

        Student[] students = {new Student("Alice"),
                new Student("Bobo"),
                new Student("Charles")};
        Student bobo = new Student("Bobo");
        int res3 = LinearSearch.search(students,bobo);
        System.out.println(res3);

    }
}

? ? ? ?其输出的结果为下图所示,表示我们所构建的search方法可以支持多种数据类型的比较:
在这里插入图片描述

3. 循环不变量

? ? ? ?循环不变量作为书写算法逻辑中非常重要的一环,简单的理解就是在循环当中一直保持不变的量。抓住了循环不变量,就能够很清楚的写出算法的逻辑。(之后大部分数据结构和算法都会分析其循环不变量)这里以一个简单的例子来说明,如下图所示:
在这里插入图片描述
? ? ? ?这里需要注意到循环体和循环不变量,其中在整个for循环当中,data[0,i-1]中没有找到目标作为整个循环的不变量,而循环体里面的if条件一旦成立,整个循环就会结束。所以,循环体if不成立时,循环就会一直进行,此时循环不变量就会一直成立,也就是说循环体维持着循环的不变量

4 时间复杂度分析

? ? ? ?不引入过多的书面语言,算法的时间复杂度表示算法的性能,且通常看最差的情况,一般用O表示,这里我们很清楚的知道。线性查找法对于一个长度为n的数组来说,最坏的情况是,整整扫描了一遍数组才找到或者根本没有找到目标值,这时候我们遍历了一遍数组,假设此时消耗的时间用T表示。因为我们要考虑到指令操作、赋值也会存在一些时间,所以T的一般化公式为T = C1 * n + C2(C1和C2都是常数)
? ? ? ?又因为我们的时间复杂度描述的是随着数据规模n的增大,算法性能的变化趋势。此时应该舍弃掉常数项,所以线性查找法的时间复杂度应该为O(n)

5 本篇小结

? ? ? ?本篇博客主要从最基础的线性查找法开始说起,涉及了循环不变量、泛型的使用、以及自定义类测试和复杂度分析的内容。文章的内容循序递进。文章有内容不对或者晦涩难懂之处,还请各位博友指出,互相学习,共同进步!

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-07-20 19:09:52  更:2022-07-20 19:13:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/18 7:09:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码