Go中实现的二进制搜索算法

Binary Search is a simple algorithm to find an item in an sorted array, and it’s usually referenced as a code sample to study when learning a new programming language.

Binary Search是一种简单的算法,可以在排序后的数组中查找项目,通常将其称为代码样本,以学习新的编程语言时进行研究。

功效 (Efficency)

It’s very efficient:

这非常有效:

  • Time: O(log n), it’s at worst logaritmic

    时间: O(log n) ,对数最差

  • Space: 0(1), takes constant time

    空间: 0(1) ,需要固定时间

理论 (Theory)

Given a sorted array, we pick the item Y in the middle and we compare it to the target value X.

给定一个排序数组,我们在中间选择项Y并将其与目标值X进行比较。

If Y matches X, we return the Y position and we exit.

如果Y与X匹配,则返回Y位置,然后退出。

We determine if X < Y, in this case we discard the right side, and we go in the middle of the left side, and we repeat the same operation as above.

我们确定是否X <Y,在这种情况下,我们丢弃右侧,然后移至左侧的中间,然后重复与上述相同的操作。

The search ends when Y finally matches X. If this does not happen, we return the position that X would have taken if it was in the array.

当Y最终与X匹配时,搜索结束。如果这没有发生,我们将返回X在数组中所处的位置。

实作 (Implementation)

We’re lucky, the Go standard library provides a binary tree implementation in its sort package, in sort.Search().

幸运的是,Go标准库在sort包中的sort.Search()提供了一个二叉树实现。

Let’s see the usage of the API, as taken from the package documentation, so we know what sort.Search should return:

让我们来看看API的用法,它来自软件包文档,因此我们知道什么样的sort.Search应该返回:

package main

import (
    "fmt"
    "sort"
)

func main() {
    a := []int{1, 3, 6, 10, 15, 21, 28, 36, 45, 55}
    x := 6

    i := sort.Search(len(a), func(i int) bool { return a[i] >= x })
    if i < len(a) && a[i] == x {
        fmt.Printf("found %d at index %d in %v\n", x, i, a)
    } else {
        fmt.Printf("%d not found in %v\n", x, a)
    }
}

sort.Search returns an index i, and we just need to make sure that that index actually contains x.

sort.Search返回一个索引i ,我们只需要确保该索引实际包含x

Of course we want to know how this is implemented internally. Since the standard library is written in Go, and open source, it’s really easy to see how sort.Search is implemented:

当然,我们想知道它是如何在内部实现的。 由于标准库是用Go语言和开源语言编写的,因此很容易看到sort.Search是如何实现的:

func Search(n int, f func(int) bool) int {
    // Define f(-1) == false and f(n) == true.
    // Invariant: f(i-1) == false, f(j) == true.
    i, j := 0, n
    for i < j {
        h := i + (j-i)/2 // avoid overflow when computing h
        // i ≤ h < j
        if !f(h) {
            i = h + 1 // preserves f(i-1) == false
        } else {
            j = h // preserves f(j) == true
        }
    }
    // i == j, f(i-1) == false, and f(j) (= f(i)) == true  =>  answer is i.
    return i
}

Let’s break it down:

让我们分解一下:

Given an array with length n, and a comparison function f (that internally evaluates x >= a[h]), we start iterating the array a.

给定一个长度为n的数组和一个比较函数f (内部计算x >= a[h] ),我们开始迭代数组a

Let’s use the actual values we use in the example, it’s easier to show what’s happening.

让我们使用示例中使用的实际值,可以更轻松地显示正在发生的事情。

Data:

数据:

a := []int{1, 3, 6, 10, 15, 21, 28, 36, 45, 55}
x := 6

Iteration 1:

迭代1:

  • i is 0, j is 9.

    i0j9

  • h is calculated as (0 + (9-0) / 2) = 4

    h计算为(0 + (9-0) / 2) = 4

  • a[h] is 15. This means we execute j = h

    a[h]15 。 这意味着我们执行j = h

Iteration 2:

迭代2:

  • i is 0, j is 4.

    i0j4

  • h is calculated as (0 + (4-0) / 2) = 2

    h计算为(0 + (4-0) / 2) = 2

  • a[h] is 6. We found the position of x, this means we return h = 2

    a[h]6 。 我们找到了x的位置,这意味着我们返回h = 2

搜索逆序 (Searching reverse order)

Since we can pass a function to sort.Search, it’s easy to search on an array sorted in the reverse order, like

由于我们可以将函数传递给sort.Search ,因此很容易在以相反顺序排序的数组上进行搜索,例如

a := []int{55, 45, 36, 28, 21, 15, 10, 6, 3, 1}
x := 6

by passing a function that compares a[i] <= x instead of a[i] >= x.

通过传递比较a[i] <= x而不是a[i] >= x

i := sort.Search(len(a), func(i int) bool { return a[i] <= x })

翻译自: https://flaviocopes.com/golang-algorithms-binary-search/

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值