PHP数据结构-线性查找与二分查找

线性查找与二分查找

欢迎来到查找的世界,在学习完各种数据结构之后,总算走到了这一步,不知道大家有什么感想呢?反正我是边学边忘,现在让我去说说图的那几个算法还是在蒙圈的状态中。不过学习嘛,就是一步一步的来,暂时搞不懂的东西其实也是可以放一放的。打破砂锅和坚持不懈当然是好的品德,但有些东西可能真的是需要时间去消化的,甚至可能是需要真实的项目经历才能彻底搞明白。在我们编程行业来说就是典型的这种实践的学习形式效果会更好,很多人在上大学的时候对于数据结构以及其它专业课都是以死记硬背为主,包括上了多少年班的同学可能都没有在业务代码中真正的使用过什么算法,所以理解它们确实是非常困难的。这时,我们可以暂时休息一下,转换一下思路,学习最主要的就是预习和复习,在这次学习完之后,将来再进行多次的复习,研究各种不同的资料,迟早有一天大家都能搞明白的。

今天的内容其实就非常简单了,可以说是除了线性表之外最简单的内容。我们只研究两个非常初级的查找,那就是顺序查找和折半查找。相信不少同学可能早就会了,一般培训机构讲数据结构和算法时,查找必讲二分,排序必讲冒泡,更不用说正规大学对口专业出身的同学了。当然,这两个也是非常简单的,不管你有没有基础,咱们一起来看看吧。

不管你是什么算法题,还是在实际的业务开发中,查找都是非常重要的,甚至可能比排序还要重要。想想你整天面向数据库编程是在干嘛?不就是 CRUD 嘛,其中大部的业务还都是以搜索查找居多,我们在优化数据库时,也主要是优化各种查询语句。当然,要说到数据库的查找那就太高深了,以后我们学习 MySQL 相关的知识时再详细讲解,特别是索引中的 B+ 树,就是数据结构和算法的核心思想的体现。好吧,不吹牛了,也不敢在这里多说了,因为自己也没研究透呢。

线性查找(顺序查找)

顾名思义,不管是叫线性还是叫顺序,很明显,就是一条数据一条数据的对比下去就好啦。

function SearchSeq($sk, $arr)
{
    for ($i = 0; $i < count($arr); $i++) {
        if ($sk == $arr[$i]) {
            echo $i, PHP_EOL;
            break;
        }
    }
    echo "线性查找次数:" . $i, PHP_EOL;
}

嗯,真的是连解释都不想解释了,这段代码要是看不懂的话就先去复习下基本的循环和条件判断语句吧!很明显,一次线性查找的时间复杂度就是 O(N) 。

二分查找(折半查找)

既然都这么简单,那么我们再直接给出折半查找的代码。

function SearchBin($sk, $arr){
    $left = 0;
    $right = count($arr) - 1;
    $i = 0;
    while ($left <= $right) {
        $i++;
        $mid = (int) (($left + $right) / 2);
        if ($arr[$mid] > $sk) {
            $right = $mid - 1;
        } else if ($arr[$mid] < $sk) {
            $left = $mid + 1;
        } else {
            echo $mid, PHP_EOL;
            break;
        }
    }
    echo "折半查找次数:" . $i, PHP_EOL;
}

折半查找的前提是数据必须是有序的,这样我们就可以根据数据问题的长度来获取中间的数,然后跟要对比的数进行比较,如果小于这个数,就在前一半数据中查找,如果大于这个数,就在后一半部分中进行查找。一会看例子再详细说明。

对比

两个算法其实都很简单,我们直接看看他们的运行情况和效率区别。

$arr = [5, 6, 19, 25, 4, 33, 56, 77, 82, 81, 64, 37, 91, 23];

// 输入 56
fscanf(STDIN, "%d", $searchKey);

SearchSeq($searchKey, $arr);
// 6
// 线性查找次数:6

sort($arr);
print_r($arr);

SearchBin($searchKey, $arr);
// 8
// 折半查找次数:3

首先我们定义了一个数组,其实就是随便给了一些数据。然后输入一个数据,查找它在数组中的位置。比如我们在测试代码中输入了 56 ,线性查找是循环进行了 6 次,找到 56 所在的位置为下标 6 的位置。

对于折半查找来说,我们需要先给数组排序,这时 56 会排在下标为 8 的位置,而在折半查找的循环中,我们只循环了 3 次就找到了这个位置。是不是感觉快了很多,一下就快了一倍。这可不是它的真正实力哦,折半查找的真实实力是 对数 级别的效率,也就是它的时间复杂度为 O(logN) 。我们先来结合上面的代码看下它这三次循环都干了什么。

  • 第一次进入,mid 为 6 (0+13=13,除2),下标为 arr[6] 的值为 3 ,比 56 小,所以 left = 6+1 = 7

  • 第二轮循环,mid 为 10(7+13=20,除2),下标为 arr[10] 的值为 77 ,比 56 大,所以 right = 10-1 = 9

  • 第三轮循环,mid 为 9(7+9=16,除2),下标为 arr[8] 的值为 56,结束

其实很多猜数字的游戏也都是这么玩的,比如给你一个范围,0-100的数,猜他写下的是哪个数,最快最简单的方法也就是这种折半查找的方式,我们只需要最多 7 次就可以猜出 100 以内的数。很明显,这就是对数的威力。下面我们再来看一个更直观的,十万个有序的数,我们就找最后那一个数,看看顺序查找和折半查找能有多大差距。

$arr = range(1, 100000);
$searchKey = 100000;

SearchSeq($searchKey, $arr);
// 99999
// 线性查找次数:99999

SearchBin($searchKey, $arr);
// 99999
// 折半查找次数:17

嗨不嗨,这就是对数的威力!!我们需要 2 的 7 次方才能覆盖 100 以内的数,但我们只需要 2 的 17 次方,就能覆盖十万以内的数,这个效率差距还是随着 N 的越来越大而越来越明显的。

总结

今天的内容是不是很简单,虽说内容简单,但是我们却见识到了不同算法效率之间的巨大差异。当然,折半查找也有其本身的局限,那就是数据必须是的序的,当然,在合适的情况下我们也可以选用一个 O(logN) 的排序算法,这样总体的时间复杂度就还能保持在对数级别了。总之,先掌握好这些简单的内容,千万别在面试的时候连这一关都过不了哦!

测试代码:

https://github.com/zhangyue0503/Data-structure-and-algorithm/blob/master/6.查找/source/6.1线性查找与二分查找.php

参考文档:

《数据结构》第二版,严蔚敏

《数据结构》第二版,陈越

《数据结构高分笔记》2020版,天勤考研

(0)

相关推荐

  • PHP中数组的区别

    PHP中数组的区别

  • 在PHP中灵活使用foreach+list处理多维数组

    先抛出问题,有时候我们接收到的参数是多维数组,我们需要将他们转成普通的数组,比如: $arr = [ [1, 2, [3, 4]], [5, 6, [7, 8]],]; 我们需要的结果是元素1变成1, ...

  • Go 数据结构和算法篇(十):二分查找的变形版本

    Go语言中文网 今天 以下文章来源于xueyuanjun ,作者xueyuanjun 日常开发过程中,除了我们上篇讲到的正常的二分查找,还有很多二分查找的变形版本,今天开始,我们就来给大家一一介绍这些 ...

  • Go 数据结构和算法篇(九):二分查找

    今天 以下文章来源于xueyuanjun ,作者xueyuanjun 介绍完基本的线性表排序算法后,今天我们来介绍一种常见的线性表查找算法 -- 二分查找. 一.二分查找的引入 对于基于数字索引的数组 ...

  • Excel公式技巧83:使用VLOOKUP进行二分查找

    excelperfect VLOOKUP函数是我们非常熟悉也很常用的一个函数.下面是其语法: VLOOKUP(lookup_value,table_array, col_index_num,[rang ...

  • (1条消息) 字节面试题:二分查找求解平方根

    x的平方根(69) 今天继续为大家分享二分法系列篇的内容,看一道比较简单的题目. 01.题目分析 这道题目是比较简单,但我认为同时也是非常经典,建议大家掌握! 第69题:x的平方根 计算并返回 x 的 ...

  • 详解二分查找算法

    我周围的人几乎都认为二分查找很简单,但事实真的如此吗?二分查找真的很简单吗?并不简单.看看 Knuth 大佬(发明 KMP 算法的那位)怎么说的: Although the basic idea of ...

  • 如何快速找出你所需要的内容——二分查找与大O表示法

    从今天开始我们将陆续介绍几种常见的算法,深入浅出地带你遨游算法的世界. 算法 现在几乎人人都在谈论算法,那么到底什么是算法?我们可以把算法看做一个菜谱,你只要按照它的指令去做,就会得到相应的结果.算法 ...

  • Python中实现二分查找的2种方法?

    公众号新增加了一个栏目,就是每天给大家解答一道Python常见的面试题,反正每天不贪多,一天一题,正好合适,只希望这个面试栏目,给那些正在准备面试的同学,提供一点点帮助! 小猿会从最基础的面试题开始, ...

  • 一图学懂信奥赛基石级考点:二分查找

    本篇文章 818 字,3 张图片,预计 7 分钟读完,收下这份二分查找的入门攻略,快来学习吧~ 关于二分查找如何学习,网络上有很多的资料,难点在于孩子如何能把这种抽象的算法具象化. 今天,小蒜头换一种 ...

  • PHP数据结构-线性表?顺序表?链表?别再傻傻分不清楚

    线性表?顺序表?链表?别再傻傻分不清楚 遵从所有教材以及各类数据结构相关的书书籍,我们先从线性表开始入门.今天这篇文章更偏概念,是关于有线性表的一个知识点的汇总. 上文说过,物理结构是用于确定数据以何 ...