通过JavaScript进行线性Vs二进制搜索

JavaScript comes with some pretty handy out-of-the-box tools for searching through an array. But with a large data set the O(n) methods like indexOf, find, or a basic loop just aren’t the best or even feasible. Instead, we can use Binary search to go over an array without looking at what we obviously don’t need, giving us a O(logn) solution.

JavaScript附带了一些非常方便的开箱即用的工具,用于搜索数组。 但是对于庞大的数据集,像indexOffind或基本循环这样的O(n)方法并不是最好的,甚至也不可行。 取而代之的是,我们可以使用二进制搜索来遍历数组,而无需查看我们显然不需要的东西,从而为我们提供了O(logn)解决方案。

先决条件 (Prerequisites)

I will be using Big O Notation when comparing performance and complexity, which you can brush up on here.

在比较性能和复杂性时,我将使用Big O表示法,您可以在此处进行介绍

实践数据 (Practice Data)

Here are some sorted and unsorted datasets, both with 50 items, that I’ll be referencing.

这里是一些有序和无序的数据集,它们都包含50个项目,我将参考它们。

const unsortedArr = [31, 27, 28, 42, 13, 8, 11, 30, 17, 41, 15, 43, 1, 36, 9, 16, 20, 35, 48, 37, 7, 26, 34, 21, 22, 6, 29, 32, 49, 10, 12, 19, 24, 38, 5, 14, 44, 40, 3, 50, 46, 25, 18, 33, 47, 4, 45, 39, 23, 2];

const sortedArr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50];

This is the standard brute-force solution I’m sure you’ve already done a thousand times. We’re just telling it, “I need something, so look through everything one-by-one until you find it”. If there’s a million times more items, it’ll take a million times longer, which nobody is going to put up with. Whether the data is sorted or not makes no difference.

这是标准的蛮力解决方案,我相信您已经做了一千遍了。 我们只是在告诉它:“我需要一些东西,所以要一遍一遍地浏览,直到找到为止。” 如果有超过一百万倍的项目,那么它将花费一百万倍,而没人会忍受。 数据是否排序没有区别。

const linear = (arr, target) => {
  let steps = 0;

  for (let i = 0; i < arr.length; i++) {
    steps++;
    if (arr[i] === target) return `Found: ${arr[i]} in ${steps} steps`;
  };
};

console.log(linear(unsortedArr, 40)); // 40 steps in 40 Milliseconds
console.log(linear(sortedArr, 40)); // 40 steps in 40 Milliseconds

Brute-forcing your way to a result is obviously a very slow and unscalable solution. Instead of wasting resources looking at data that’s obviously not what we want, we can use a ‘divide-and-conquer’ approach to make each operation focus on ignoring what we don’t want instead of painfully looking for what we do want.

蛮力逼近结果显然是一个非常缓慢且不可扩展的解决方案。 与其浪费资源来查看显然不是我们想要的数据,我们可以使用“分而治之”的方法,使每个操作着重于忽略我们不需要的内容,而不是痛苦地寻找我们想要的内容。

We have three main components, two pointers and one pivot. Each pointer starts at the either end of the array with the pivot in the center. Then we check if what we want is higher or lower than our pivot, if higher then the left pointer is moved to the pivot’s position while the pivot moved to the new middle. We keep running this until our pivot is equal to our target.

我们有三个主要组成部分,两个指针和一个枢轴。 每个指针都从数组的任一端开始,枢轴位于中心。 然后,我们检查所需的位置是否高于或低于枢轴,如果高于或低于枢轴,则将左指针移至枢轴的位置,同时枢轴移至新的中间位置。 我们一直在运行它直到我们的枢轴等于我们的目标。

With each step we are cutting our data set in half, completely ignoring what we don’t need, giving us a time complexity of O(logn). If we ran a search for a number in an array of a million items that took ten steps, a billion item search may only take 15-20 steps.

每一步,我们都将数据集切成两半,完全忽略了我们不需要的内容,这给我们带来了O(logn)的时间复杂度。 如果我们对一百万个项目的数组中的某个数字进行了十步搜索,那么十亿个项目中的搜索可能仅需15-20步。

const binary = (arr, target) => {
  let start = 0;
  let end = arr.length;
  let pivot = Math.floor((start + end) / 2);
  let steps = 0;

  for (let i = 0; i < arr.length; i++) {
    if (arr[pivot] !== target) {
      if (target < arr[pivot]) end = pivot;
      else start = pivot;
      pivot = Math.floor((start + end) / 2);
      steps++;
    };

    if (arr[pivot] === target) return `Found: ${target} in ${steps} steps`;
  };

  return 'Nothing Found';
};

console.log(linear(unsortedArr, 40)); // Nothing Found
console.log(binary(arr, 44)); // 5 steps in 8 Milliseconds
console.log(binary(arr, 43)); // 2 steps in 7 Milliseconds

Binary search comes with the big drawback of only allowing us to do this on sorted arrays, but there are other solutions based around pre-sorting your data before a search.

二进制搜索的最大缺点是仅允许我们对排序的数组执行此操作,但是还有其他解决方案,它们基于在搜索之前对数据进行预排序。

结论 (Conclusion)

This is only one way of applying a binary search but the idea can be reconfigured for various data structures, as long as it’s sorted. In the future, I hope we can explore using this technique for traversing more advanced datasets at lightning fast speeds ⚡.

这只是应用二进制搜索的一种方法,但是只要对它进行排序,就可以将其重新配置为各种数据结构。 将来,我希望我们可以探索使用此技术以闪电般的速度遍历更高级的数据集。

翻译自: https://www.digitalocean.com/community/tutorials/js-linear-vs-binary-search

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值