0

0

二分查找算法的 JavaScript 实现

王林

王林

发布时间:2023-08-29 17:53:05

|

925人浏览过

|

来源于php中文网

原创

在这篇文章中,我将比较线性搜索和二分搜索算法。您将学习线性和二进制算法的伪代码,查看演示这两种方法的示例,了解时间复杂度,并获得有关如何实现算法的分步指南。

简介

作为一名程序员,您希望找到问题的最佳解决方案,以便您的代码不仅正确而且高效。选择次优算法可能意味着更长的完成时间、增加的代码复杂性,或更糟糕的是,程序崩溃。

您可能使用过搜索算法来定位数据集合中的项目。 JavaScript 语言有多种方法(例如 find)来查找数组中的项目。然而,这些方法使用线性搜索。线性搜索算法从列表的开头开始,将每个元素与搜索值进行比较,直到找到为止。

当元素数量较少时,这很好。但是,当您搜索包含数千或数百万个元素的大型列表时,您需要一种更好的方法来定位项目。这是您使用二分搜索的时候。

在本教程中,我将解释二分搜索的工作原理以及如何在 JavaScript 中实现该算法。首先,我们回顾一下线性搜索算法。

立即学习Java免费学习笔记(深入)”;

线性搜索

我们将首先解释如何在 JavaScript 中实现线性搜索。我们将创建一个名为 linearSearch 的函数,该函数接受整数或字符串和数组作为参数。该函数将在数组中的每个元素中搜索该值,如果找到,则返回该值在数组中的位置。如果数组中没有该值,则返回-1

线性搜索的伪代码

Set found to false
Set position to −1
Set index to 0
while found is false and index < number of elements
    if list[index] is equal to search value
        Set found to true
        Set position to index
    else Add 1 to index
return position

线性搜索的逐步说明

假设我们线性搜索的输入是 [1,9,13,16,3,4,0,12]。如果我们要搜索的值是 16,则上述逻辑将返回 3。并且,如果我们搜索 11,上述逻辑将返回 -1。让我们来分解一下。

二分查找算法的 JavaScript 实现

我们通过将 found 设置为 false,将 position 设置为 -1,并将 index 设置为 0 来初始化算法。然后我们迭代:

步骤 index 列表[索引] 位置 找到
1 0 1 -1 false
2 1 9 -1 false
3 2 13 -1 false
4 3 16 3 true

如果我们对数组中不存在的元素遵循上述逻辑,您将看到代码返回 -1,因为 found = false,并且 position = -1 直到最后。 p>

线性搜索的Javascript实现

这是线性搜索算法的 JavaScript 实现:

function linearSearch(value, list) {
    let found = false;
    let position = -1;
    let index = 0;
 
    while(!found && index < list.length) {
        if(list[index] == value) {
            found = true;
            position = index;
        } else {
            index += 1;
        }
    }
    return position;
}

线性搜索的属性

需要注意的是,线性搜索算法不需要使用排序列表。此外,该算法可以定制以用于不同的场景,例如通过键搜索对象数组。如果您有一个包含名字和姓氏键的客户数据数组,您可以测试该数组是否包含具有指定名字的客户。在这种情况下,您不需要检查 list[index] 是否等于我们的搜索值,而是检查 list[index].first

线性搜索的时间复杂度

如果搜索的元素是列表中的第一个元素,则可以实现最佳情况的时间复杂度。现在,搜索只需一次比较即可完成。因此,最好情况的时间复杂度为O(1)

如果搜索的元素是最后一个元素或者不存在于列表中,则会出现最坏情况的时间复杂度。在这种情况下,搜索必须比较数组中的所有元素。我们说输入数据的长度为 n,这意味着由于进行了 n 次比较,总体时间复杂度为 O(n)

在上面的示例中,我在包含八个元素的数组上使用了 linearSearch 函数。在最坏的情况下,当搜索值不在列表中或位于列表末尾时,该函数将必须进行八次比较。因为我们的数组很小,所以不需要使用不同的算法进行优化。然而,超过某一点,使用线性搜索算法就不再有效,这时使用二分搜索算法会更好。

线性搜索的平均时间复杂度也是O(n)

线性搜索的空间复杂度

该算法的整体空间复杂度相当于数组的大小。因此,O(n)。您不需要保留任何额外的空间来完成此算法。

二分查找

假设您正在玩一个猜数字游戏。系统会要求您猜测 1 到 100 之间的一个数字。如果您的数字过高或过低,您将会得到提示。

您的策略是什么?你会随机选择数字吗?您会从 1 开始,然后是 2,依此类推,直到您猜对为止?即使您有无限的猜测,您也希望在尽可能少的尝试中做出正确的猜测。因此,您可以从猜测 50 开始。如果数字较大,您可以猜测 75。如果数字较小,则意味着数字在 50 到 75 之间,您会选择中间的数字。你会继续这样,直到得到正确的数字。这类似于二分搜索的工作原理。

有两种实现二分查找的方法:

  • 迭代法
  • 递归方法

迭代二分搜索的伪代码

下面是一些使用迭代方法表达二分搜索的伪代码:

do until the low and high pointers have not met or crossed
    mid = (low + high)/2
    if (x == arr[mid])
        return mid
    else if (x > arr[mid]) 
        low = mid + 1
    else                     
        high = mid - 1

递归二分搜索的伪代码

这是使用递归方法实现二分查找的伪代码。

binarySearch(arr, x, low, high)
    if low > high
        return False 
    else
        mid = (low + high) / 2 
        if x == arr[mid]
            return mid
        else if x > arr[mid]    
            return binarySearch(arr, x, mid + 1, high)
        else                              
            return binarySearch(arr, x, low, mid - 1)

无论使用何种技术,二分搜索算法始终使用分而治之的方法。

分步说明

让我们考虑一个数组 [1,9,13,16,3,5,0,12],其中 searchValue13

Magic AI Avatars
Magic AI Avatars

神奇的AI头像,获得200多个由AI制作的自定义头像。

下载

我们从执行二分搜索所需的排序数组开始。请注意,对数组进行排序的成本很高,但一旦完成,就可以多次有效地搜索该数组。

二分查找算法的 JavaScript 实现

现在,高指针和低指针将分别设置为第一个和最后一个元素。中间指针设置为 (low - high) / 2 给出的索引。

二分查找算法的 JavaScript 实现

由于 searchValue > mid,我们需要搜索数组的右侧。因此,我们将 low 指针设置为紧接在 mid 之后,并将 mid 重置为位于 lowhigh 指针之间。

二分查找算法的 JavaScript 实现

同样,目标值位于数组的右侧。我们再次调整低指针和高指针。现在低和中指针是相同的。

二分查找算法的 JavaScript 实现

现在,在 mid 处找到了 searchValue,这意味着我们已经到达搜索的末尾!

步骤 low mid high 列表[mid]
1 0 3 7 5
2 4 5 7 9
3 6 6 7 13

二分查找的Javascript实现

现在让我们用 JavaScript 编写二分搜索算法!

我们将创建一个函数 binarySearch,它接受一个值和一个数组作为参数。如果找到该值,它将返回列表中出现该值的索引。如果没有找到该值,则返回-1。这是我们用 JavaScript 编写的实现:

//note that list must be sorted for this function to work
function binarySearch(value, list) {
    let low = 0;    //left endpoint
    let high = list.length - 1;   //right endpoint
    let position = -1;
    let found = false;
    let mid;
 
    while (found === false && low <= high) {
        mid = Math.floor((low + high)/2);
        if (list[mid] == value) {
            found = true;
            position = mid;
        } else if (list[mid] > value) {  //if in lower half
            high = mid - 1;
        } else {  //in in upper half
            low = mid + 1;
        }
    }
    return position;
}

时间复杂度

我们使用二分搜索来查找数组中的元素的主要原因之一是它的时间复杂度。在最佳情况下,二分查找的时间复杂度为O(1)。当数组中间的元素与搜索元素匹配时,就会发生这种情况。

在最坏的情况下,使用二分搜索搜索元素的时间复杂度为 O(log n) — 对于较大的 n 值,远低于 O(n)。要了解 log(n) 的增长速度比 n 慢多少,这里有一个 log(n) 典型值表.

n 日志(n)
1 1
8 3
1024 10
1,000,000 19.9
1,000,000,000,000,000,000 59.8

因此,正如您所看到的,n 越大,二分搜索相对于线性搜索的改进就越大。

对于使用二分搜索来搜索项目,平均情况时间复杂度也是O(log n)

空间复杂度

实现二分查找的空间复杂度还是O(n)

二分查找的属性

与线性搜索不同,二分搜索使用排序列表。这让我们可以使用“分而治之”的算法来解决问题。

结论

在本教程中,我们了解了如何实现线性搜索和二分搜索算法。线性搜索算法更简单,并且不需要排序数组。然而,使用较大的数组效率很低。在最坏的情况下,算法必须搜索所有元素进行 n 次比较(其中 n 是元素数量)。

二分查找算法则需要先对数组进行排序,并且实现起来比较复杂。然而,即使考虑到排序成本,它的效率也更高。例如,具有 10 个元素的数组对于二分搜索最多进行 4 次比较,而对于线性搜索则最多进行 10 次比较,这并不是一个很大的改进。然而,对于具有 1,000,000 个元素的数组,二分查找的最坏情况也只有 20 次比较。这相对于线性搜索来说是一个巨大的改进!

了解如何使用二分搜索不仅仅是面试问题的练习。这是一项实用技能,可以让您的代码更高效地工作。

这篇文章已根据 Divya Dev 的贡献进行了更新。 Divya 是一位拥有五年以上经验的前端开发人员。她是安娜大学的毕业生和金牌获得者。

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

760

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1567

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

649

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

1228

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

1204

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

193

2025.07.29

c++字符串相关教程
c++字符串相关教程

本专题整合了c++字符串相关教程,阅读专题下面的文章了解更多详细内容。

131

2025.08.07

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号