3-1 二分搜索与线性搜索(对已排序列表)

二分搜索与线性搜索(对已排序列表)

在已排序的列表中查找一个目标元素,有两种经典方法:

  • 线性搜索(Linear Search):从左到右逐个扫描每个元素,直到找到目标或遍历完整个列表。时间复杂度为 O(n)。
  • 二分搜索(Binary Search):利用"分治法(Divide and Conquer)"的思想,每次将搜索范围缩小一半,时间复杂度为 O(log n)。但要求数据必须已排序

以已排序数组 [1, 3, 5, 7, 9, 11, 13] 为例,查找目标值 7,二分搜索的过程如下:

数组:  [1, 3, 5, 7, 9, 11, 13]
索引:   0  1  2  3  4   5   6

第1步: low=0, high=6, mid=3 → arr[3]=7 == 目标7,找到!
       [1, 3, 5, 7, 9, 11, 13]
                   ^
                  mid

仅需 1 次比较即可定位目标,而线性搜索需要 4 次。

对于更大的数组,二分搜索的优势更加明显。例如在 1000 个元素的数组中查找,线性搜索最多需要 1000 次比较,而二分搜索最多只需要 10 次。


线性搜索

线性搜索是最简单的搜索算法:从数组的第一个元素开始,依次与目标值比较,直到找到匹配的元素或遍历完整个数组。

基本思路:

  • 从索引 0 开始,逐一比较每个元素与目标值。
  • 如果找到匹配项,返回该索引。
  • 如果遍历完整个数组仍未找到,返回 -1 表示未找到。

C++ 实现

#include <iostream>

// linear search: scan each element sequentially
int linearSearch(int arr[], int n, int target)
{
    for (int i = 0; i < n; i++)
    {
        if (arr[i] == target)
        {
            return i;  // found at index i
        }
    }
    return -1;  // not found
}

int main()
{
    int arr[] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
    int n = sizeof(arr) / sizeof(arr[0]);

    // search for existing element
    int target1 = 14;
    int result1 = linearSearch(arr, n, target1);
    if (result1 != -1)
    {
        std::cout << "Found " << target1 << " at index " << result1 << "\n";
    }
    else
    {
        std::cout << target1 << " not found in the array\n";
    }

    // search for non-existing element
    int target2 = 15;
    int result2 = linearSearch(arr, n, target2);
    if (result2 != -1)
    {
        std::cout << "Found " << target2 << " at index " << result2 << "\n";
    }
    else
    {
        std::cout << target2 << " not found in the array\n";
    }

    return 0;
}

运行该程序将输出

Found 14 at index 6
15 not found in the array

C 实现

#include <stdio.h>

// linear search: scan each element sequentially
int linearSearch(int arr[], int n, int target)
{
    for (int i = 0; i < n; i++)
    {
        if (arr[i] == target)
        {
            return i;  // found at index i
        }
    }
    return -1;  // not found
}

int main()
{
    int arr[] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
    int n = sizeof(arr) / sizeof(arr[0]);

    // search for existing element
    int target1 = 14;
    int result1 = linearSearch(arr, n, target1);
    if (result1 != -1)
    {
        printf("Found %d at index %d\n", target1, result1);
    }
    else
    {
        printf("%d not found in the array\n", target1);
    }

    // search for non-existing element
    int target2 = 15;
    int result2 = linearSearch(arr, n, target2);
    if (result2 != -1)
    {
        printf("Found %d at index %d\n", target2, result2);
    }
    else
    {
        printf("%d not found in the array\n", target2);
    }

    return 0;
}

运行该程序将输出

Found 14 at index 6
15 not found in the array

Python 实现

def linear_search(arr, target):
    """Linear search: scan each element sequentially."""
    for i in range(len(arr)):
        if arr[i] == target:
            return i  # found at index i
    return -1  # not found

arr = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

# search for existing element
target1 = 14
result1 = linear_search(arr, target1)
if result1 != -1:
    print(f"Found {target1} at index {result1}")
else:
    print(f"{target1} not found in the array")

# search for non-existing element
target2 = 15
result2 = linear_search(arr, target2)
if result2 != -1:
    print(f"Found {target2} at index {result2}")
else:
    print(f"{target2} not found in the array")

运行该程序将输出

Found 14 at index 6
15 not found in the array

Go 实现

package main

import "fmt"

// linear search: scan each element sequentially
func linearSearch(arr []int, target int) int {
    for i := 0; i < len(arr); i++ {
        if arr[i] == target {
            return i // found at index i
        }
    }
    return -1 // not found
}

func main() {
    arr := []int{2, 4, 6, 8, 10, 12, 14, 16, 18, 20}

    // search for existing element
    target1 := 14
    result1 := linearSearch(arr, target1)
    if result1 != -1 {
        fmt.Printf("Found %d at index %d\n", target1, result1)
    } else {
        fmt.Printf("%d not found in the array\n", target1)
    }

    // search for non-existing element
    target2 := 15
    result2 := linearSearch(arr, target2)
    if result2 != -1 {
        fmt.Printf("Found %d at index %d\n", target2, result2)
    } else {
        fmt.Printf("%d not found in the array\n", target2)
    }
}

运行该程序将输出

Found 14 at index 6
15 not found in the array

Go 版本使用切片(slice)作为数组参数,线性搜索逻辑与 C++/Python 版本完全一致:从索引 0 开始逐个比较,找到返回索引,遍历完毕未找到则返回 -1。

查找目标 14 时,函数从索引 0 开始依次比较,经过 2、4、6、8、10、12 共 6 次比较后,在索引 6 处找到 14。查找 15 时,需要遍历整个数组(10 次比较)才能确认不存在。


二分搜索(迭代法)

二分搜索(迭代法)通过维护一个搜索范围 [low, high],每次取中间元素与目标值比较,根据比较结果将搜索范围缩小一半:

  • 若中间值等于目标值,搜索成功。
  • 若中间值小于目标值,说明目标在右半部分,将 low 移到 mid + 1
  • 若中间值大于目标值,说明目标在左半部分,将 high 移到 mid - 1

以数组 [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] 查找目标 14 为例:

数组:  [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
索引:   0  1  2  3   4   5   6   7   8   9

第1步: low=0, high=9, mid=(0+9)/2=4
       arr[4]=10 < 14 → 目标在右半部分,low=mid+1=5
       [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
                       ^^^^^^^^^^^^^^^^^^^^
                       搜索范围 [5, 9]

第2步: low=5, high=9, mid=(5+9)/2=7
       arr[7]=16 > 14 → 目标在左半部分,high=mid-1=6
       [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
                           ^^^
                           搜索范围 [5, 6]

第3步: low=5, high=6, mid=(5+6)/2=5
       arr[5]=12 < 14 → 目标在右半部分,low=mid+1=6
       [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
                               ^
                               搜索范围 [6, 6]

第4步: low=6, high=6, mid=(6+6)/2=6
       arr[6]=14 == 14 → 找到目标!返回索引 6

仅用 4 次比较就找到了目标,而线性搜索也需要 7 次比较。

C++ 实现

#include <iostream>

// binary search (iterative): halve the range each step
int binarySearch(int arr[], int n, int target)
{
    int low = 0;
    int high = n - 1;

    while (low <= high)
    {
        int mid = low + (high - low) / 2;  // avoid overflow

        if (arr[mid] == target)
        {
            return mid;  // found
        }
        else if (arr[mid] < target)
        {
            low = mid + 1;  // search right half
        }
        else
        {
            high = mid - 1;  // search left half
        }
    }

    return -1;  // not found
}

int main()
{
    int arr[] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
    int n = sizeof(arr) / sizeof(arr[0]);

    // search for existing element
    int target1 = 14;
    int result1 = binarySearch(arr, n, target1);
    if (result1 != -1)
    {
        std::cout << "Found " << target1 << " at index " << result1 << "\n";
    }
    else
    {
        std::cout << target1 << " not found in the array\n";
    }

    // search for non-existing element
    int target2 = 15;
    int result2 = binarySearch(arr, n, target2);
    if (result2 != -1)
    {
        std::cout << "Found " << target2 << " at index " << result2 << "\n";
    }
    else
    {
        std::cout << target2 << " not found in the array\n";
    }

    return 0;
}

运行该程序将输出

Found 14 at index 6
15 not found in the array

C 实现

#include <stdio.h>

// binary search (iterative): halve the range each step
int binarySearch(int arr[], int n, int target)
{
    int low = 0;
    int high = n - 1;

    while (low <= high)
    {
        int mid = low + (high - low) / 2;  // avoid overflow

        if (arr[mid] == target)
        {
            return mid;  // found
        }
        else if (arr[mid] < target)
        {
            low = mid + 1;  // search right half
        }
        else
        {
            high = mid - 1;  // search left half
        }
    }

    return -1;  // not found
}

int main()
{
    int arr[] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
    int n = sizeof(arr) / sizeof(arr[0]);

    // search for existing element
    int target1 = 14;
    int result1 = binarySearch(arr, n, target1);
    if (result1 != -1)
    {
        printf("Found %d at index %d\n", target1, result1);
    }
    else
    {
        printf("%d not found in the array\n", target1);
    }

    // search for non-existing element
    int target2 = 15;
    int result2 = binarySearch(arr, n, target2);
    if (result2 != -1)
    {
        printf("Found %d at index %d\n", target2, result2);
    }
    else
    {
        printf("%d not found in the array\n", target2);
    }

    return 0;
}

运行该程序将输出

Found 14 at index 6
15 not found in the array

Python 实现

def binary_search(arr, target):
    """Binary search (iterative): halve the range each step."""
    low = 0
    high = len(arr) - 1

    while low <= high:
        mid = low + (high - low) // 2  # avoid overflow

        if arr[mid] == target:
            return mid  # found
        elif arr[mid] < target:
            low = mid + 1  # search right half
        else:
            high = mid - 1  # search left half

    return -1  # not found

arr = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

# search for existing element
target1 = 14
result1 = binary_search(arr, target1)
if result1 != -1:
    print(f"Found {target1} at index {result1}")
else:
    print(f"{target1} not found in the array")

# search for non-existing element
target2 = 15
result2 = binary_search(arr, target2)
if result2 != -1:
    print(f"Found {target2} at index {result2}")
else:
    print(f"{target2} not found in the array")

运行该程序将输出

Found 14 at index 6
15 not found in the array

Go 实现

package main

import "fmt"

// binary search (iterative): halve the range each step
func binarySearch(arr []int, target int) int {
    low := 0
    high := len(arr) - 1

    for low <= high {
        mid := low + (high-low)/2 // avoid overflow

        if arr[mid] == target {
            return mid // found
        } else if arr[mid] < target {
            low = mid + 1 // search right half
        } else {
            high = mid - 1 // search left half
        }
    }

    return -1 // not found
}

func main() {
    arr := []int{2, 4, 6, 8, 10, 12, 14, 16, 18, 20}

    // search for existing element
    target1 := 14
    result1 := binarySearch(arr, target1)
    if result1 != -1 {
        fmt.Printf("Found %d at index %d\n", target1, result1)
    } else {
        fmt.Printf("%d not found in the array\n", target1)
    }

    // search for non-existing element
    target2 := 15
    result2 := binarySearch(arr, target2)
    if result2 != -1 {
        fmt.Printf("Found %d at index %d\n", target2, result2)
    } else {
        fmt.Printf("%d not found in the array\n", target2)
    }
}

运行该程序将输出

Found 14 at index 6
15 not found in the array

Go 版本的迭代二分搜索使用 low + (high - low) / 2 计算中间位置以避免整数溢出,与 C++/Python 版本的逻辑完全一致。

查找 14 时经过 4 次比较即找到目标。查找 15 时,搜索范围逐步缩小至 low > high,确认 15 不在数组中。注意中间值的计算使用 low + (high - low) / 2 而非 (low + high) / 2,这是为了避免 low + high 在极大数组时发生整数溢出。


二分搜索(递归法)

递归法实现二分搜索的核心思想与迭代法相同,只是将"缩小搜索范围"的过程用递归调用替代:

  • 基准情形(Base Case):当 low > high 时,搜索范围为空,返回 -1 表示未找到。
  • 递推步骤(Recursive Step):计算中间位置 mid,若中间值等于目标则返回;否则对左半部分或右半部分递归搜索。

以查找目标 14 为例,递归调用树如下:

binarySearchRecursive(arr, 0, 9, 14)
  mid=4, arr[4]=10 < 14
  └─ binarySearchRecursive(arr, 5, 9, 14)
       mid=7, arr[7]=16 > 14
       └─ binarySearchRecursive(arr, 5, 6, 14)
            mid=5, arr[5]=12 < 14
            └─ binarySearchRecursive(arr, 6, 6, 14)
                 mid=6, arr[6]=14 == 14
                 └─ return 6  ← found!

C++ 实现

#include <iostream>

// binary search (recursive): divide and conquer
int binarySearchRecursive(int arr[], int low, int high, int target)
{
    // base case: search range is empty
    if (low > high)
    {
        return -1;  // not found
    }

    int mid = low + (high - low) / 2;  // avoid overflow

    if (arr[mid] == target)
    {
        return mid;  // found
    }
    else if (arr[mid] < target)
    {
        // search right half
        return binarySearchRecursive(arr, mid + 1, high, target);
    }
    else
    {
        // search left half
        return binarySearchRecursive(arr, low, mid - 1, target);
    }
}

int main()
{
    int arr[] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
    int n = sizeof(arr) / sizeof(arr[0]);

    // search for existing element
    int target1 = 14;
    int result1 = binarySearchRecursive(arr, 0, n - 1, target1);
    if (result1 != -1)
    {
        std::cout << "Found " << target1 << " at index " << result1 << "\n";
    }
    else
    {
        std::cout << target1 << " not found in the array\n";
    }

    // search for non-existing element
    int target2 = 15;
    int result2 = binarySearchRecursive(arr, 0, n - 1, target2);
    if (result2 != -1)
    {
        std::cout << "Found " << target2 << " at index " << result2 << "\n";
    }
    else
    {
        std::cout << target2 << " not found in the array\n";
    }

    return 0;
}

运行该程序将输出

Found 14 at index 6
15 not found in the array

C 实现

#include <stdio.h>

// binary search (recursive): divide and conquer
int binarySearchRecursive(int arr[], int low, int high, int target)
{
    // base case: search range is empty
    if (low > high)
    {
        return -1;  // not found
    }

    int mid = low + (high - low) / 2;  // avoid overflow

    if (arr[mid] == target)
    {
        return mid;  // found
    }
    else if (arr[mid] < target)
    {
        // search right half
        return binarySearchRecursive(arr, mid + 1, high, target);
    }
    else
    {
        // search left half
        return binarySearchRecursive(arr, low, mid - 1, target);
    }
}

int main()
{
    int arr[] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
    int n = sizeof(arr) / sizeof(arr[0]);

    // search for existing element
    int target1 = 14;
    int result1 = binarySearchRecursive(arr, 0, n - 1, target1);
    if (result1 != -1)
    {
        printf("Found %d at index %d\n", target1, result1);
    }
    else
    {
        printf("%d not found in the array\n", target1);
    }

    // search for non-existing element
    int target2 = 15;
    int result2 = binarySearchRecursive(arr, 0, n - 1, target2);
    if (result2 != -1)
    {
        printf("Found %d at index %d\n", target2, result2);
    }
    else
    {
        printf("%d not found in the array\n", target2);
    }

    return 0;
}

运行该程序将输出

Found 14 at index 6
15 not found in the array

Python 实现

def binary_search_recursive(arr, low, high, target):
    """Binary search (recursive): divide and conquer."""
    # base case: search range is empty
    if low > high:
        return -1  # not found

    mid = low + (high - low) // 2  # avoid overflow

    if arr[mid] == target:
        return mid  # found
    elif arr[mid] < target:
        # search right half
        return binary_search_recursive(arr, mid + 1, high, target)
    else:
        # search left half
        return binary_search_recursive(arr, low, mid - 1, target)

arr = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
n = len(arr)

# search for existing element
target1 = 14
result1 = binary_search_recursive(arr, 0, n - 1, target1)
if result1 != -1:
    print(f"Found {target1} at index {result1}")
else:
    print(f"{target1} not found in the array")

# search for non-existing element
target2 = 15
result2 = binary_search_recursive(arr, 0, n - 1, target2)
if result2 != -1:
    print(f"Found {target2} at index {result2}")
else:
    print(f"{target2} not found in the array")

运行该程序将输出

Found 14 at index 6
15 not found in the array

Go 实现

package main

import "fmt"

// binary search (recursive): divide and conquer
func binarySearchRecursive(arr []int, low, high, target int) int {
    // base case: search range is empty
    if low > high {
        return -1 // not found
    }

    mid := low + (high-low)/2 // avoid overflow

    if arr[mid] == target {
        return mid // found
    } else if arr[mid] < target {
        // search right half
        return binarySearchRecursive(arr, mid+1, high, target)
    } else {
        // search left half
        return binarySearchRecursive(arr, low, mid-1, target)
    }
}

func main() {
    arr := []int{2, 4, 6, 8, 10, 12, 14, 16, 18, 20}
    n := len(arr)

    // search for existing element
    target1 := 14
    result1 := binarySearchRecursive(arr, 0, n-1, target1)
    if result1 != -1 {
        fmt.Printf("Found %d at index %d\n", target1, result1)
    } else {
        fmt.Printf("%d not found in the array\n", target1)
    }

    // search for non-existing element
    target2 := 15
    result2 := binarySearchRecursive(arr, 0, n-1, target2)
    if result2 != -1 {
        fmt.Printf("Found %d at index %d\n", target2, result2)
    } else {
        fmt.Printf("%d not found in the array\n", target2)
    }
}

运行该程序将输出

Found 14 at index 6
15 not found in the array

Go 递归版本的 binarySearchRecursive 函数接受切片和边界索引作为参数,逻辑与 C++/Python 递归版本完全等价。每次递归调用将搜索范围缩小一半,直到找到目标或范围为空。

递归法的逻辑与迭代法完全等价,只是将 while 循环替换为递归调用。每次递归调用将搜索范围缩小一半,直到找到目标或范围为空。注意递归法的空间复杂度为 O(log n)(递归调用栈),而迭代法仅为 O(1)。


完整对比

下面给出一个完整的程序,在同一数据集上同时运行线性搜索和二分搜索(迭代法、递归法),对比它们的搜索结果。

C++ 实现

#include <iostream>

// linear search
int linearSearch(int arr[], int n, int target)
{
    for (int i = 0; i < n; i++)
    {
        if (arr[i] == target)
        {
            return i;
        }
    }
    return -1;
}

// binary search (iterative)
int binarySearch(int arr[], int n, int target)
{
    int low = 0;
    int high = n - 1;

    while (low <= high)
    {
        int mid = low + (high - low) / 2;
        if (arr[mid] == target)
        {
            return mid;
        }
        else if (arr[mid] < target)
        {
            low = mid + 1;
        }
        else
        {
            high = mid - 1;
        }
    }
    return -1;
}

// binary search (recursive)
int binarySearchRecursive(int arr[], int low, int high, int target)
{
    if (low > high)
    {
        return -1;
    }

    int mid = low + (high - low) / 2;

    if (arr[mid] == target)
    {
        return mid;
    }
    else if (arr[mid] < target)
    {
        return binarySearchRecursive(arr, mid + 1, high, target);
    }
    else
    {
        return binarySearchRecursive(arr, low, mid - 1, target);
    }
}

int main()
{
    int arr[] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
    int n = sizeof(arr) / sizeof(arr[0]);
    int targets[] = {14, 15, 2, 20};
    int numTargets = sizeof(targets) / sizeof(targets[0]);

    std::cout << "Array: ";
    for (int i = 0; i < n; i++)
    {
        std::cout << arr[i];
        if (i < n - 1) std::cout << " ";
    }
    std::cout << "\n\n";

    for (int i = 0; i < numTargets; i++)
    {
        int t = targets[i];
        int r1 = linearSearch(arr, n, t);
        int r2 = binarySearch(arr, n, t);
        int r3 = binarySearchRecursive(arr, 0, n - 1, t);

        std::cout << "Target " << t << ":\n";
        std::cout << "  Linear Search:        "
                  << (r1 != -1 ? "index " + std::to_string(r1) : "not found") << "\n";
        std::cout << "  Binary Search (iter): "
                  << (r2 != -1 ? "index " + std::to_string(r2) : "not found") << "\n";
        std::cout << "  Binary Search (rec):  "
                  << (r3 != -1 ? "index " + std::to_string(r3) : "not found") << "\n";
        std::cout << "\n";
    }

    return 0;
}

运行该程序将输出

Array: 2 4 6 8 10 12 14 16 18 20

Target 14:
  Linear Search:        index 6
  Binary Search (iter): index 6
  Binary Search (rec):  index 6

Target 15:
  Linear Search:        not found
  Binary Search (iter): not found
  Binary Search (rec):  not found

Target 2:
  Linear Search:        index 0
  Binary Search (iter): index 0
  Binary Search (rec):  index 0

Target 20:
  Linear Search:        index 9
  Binary Search (iter): index 9
  Binary Search (rec):  index 9

C 实现

#include <stdio.h>

// linear search
int linearSearch(int arr[], int n, int target)
{
    for (int i = 0; i < n; i++)
    {
        if (arr[i] == target)
        {
            return i;
        }
    }
    return -1;
}

// binary search (iterative)
int binarySearch(int arr[], int n, int target)
{
    int low = 0;
    int high = n - 1;

    while (low <= high)
    {
        int mid = low + (high - low) / 2;
        if (arr[mid] == target)
        {
            return mid;
        }
        else if (arr[mid] < target)
        {
            low = mid + 1;
        }
        else
        {
            high = mid - 1;
        }
    }
    return -1;
}

// binary search (recursive)
int binarySearchRecursive(int arr[], int low, int high, int target)
{
    if (low > high)
    {
        return -1;
    }

    int mid = low + (high - low) / 2;

    if (arr[mid] == target)
    {
        return mid;
    }
    else if (arr[mid] < target)
    {
        return binarySearchRecursive(arr, mid + 1, high, target);
    }
    else
    {
        return binarySearchRecursive(arr, low, mid - 1, target);
    }
}

int main()
{
    int arr[] = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
    int n = sizeof(arr) / sizeof(arr[0]);
    int targets[] = {14, 15, 2, 20};
    int numTargets = sizeof(targets) / sizeof(targets[0]);

    printf("Array: ");
    for (int i = 0; i < n; i++)
    {
        printf("%d", arr[i]);
        if (i < n - 1) printf(" ");
    }
    printf("\n\n");

    for (int i = 0; i < numTargets; i++)
    {
        int t = targets[i];
        int r1 = linearSearch(arr, n, t);
        int r2 = binarySearch(arr, n, t);
        int r3 = binarySearchRecursive(arr, 0, n - 1, t);

        printf("Target %d:\n", t);
        printf("  Linear Search:        %s\n",
               r1 != -1 ? "found" : "not found");
        printf("  Binary Search (iter): %s\n",
               r2 != -1 ? "found" : "not found");
        printf("  Binary Search (rec):  %s\n",
               r3 != -1 ? "found" : "not found");
        printf("\n");
    }

    return 0;
}

运行该程序将输出

Array: 2 4 6 8 10 12 14 16 18 20

Target 14:
  Linear Search:        found
  Binary Search (iter): found
  Binary Search (rec):  found

Target 15:
  Linear Search:        not found
  Binary Search (rec):  not found
  Binary Search (rec):  not found

Target 2:
  Linear Search:        found
  Binary Search (iter): found
  Binary Search (rec):  found

Target 20:
  Linear Search:        found
  Binary Search (iter): found
  Binary Search (rec):  found

Python 实现

def linear_search(arr, target):
    """Linear search."""
    for i in range(len(arr)):
        if arr[i] == target:
            return i
    return -1

def binary_search(arr, target):
    """Binary search (iterative)."""
    low = 0
    high = len(arr) - 1

    while low <= high:
        mid = low + (high - low) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            low = mid + 1
        else:
            high = mid - 1
    return -1

def binary_search_recursive(arr, low, high, target):
    """Binary search (recursive)."""
    if low > high:
        return -1

    mid = low + (high - low) // 2

    if arr[mid] == target:
        return mid
    elif arr[mid] < target:
        return binary_search_recursive(arr, mid + 1, high, target)
    else:
        return binary_search_recursive(arr, low, mid - 1, target)

arr = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
targets = [14, 15, 2, 20]

print(f"Array: {' '.join(str(x) for x in arr)}\n")

for t in targets:
    r1 = linear_search(arr, t)
    r2 = binary_search(arr, t)
    r3 = binary_search_recursive(arr, 0, len(arr) - 1, t)

    print(f"Target {t}:")
    print(f"  Linear Search:        {'index ' + str(r1) if r1 != -1 else 'not found'}")
    print(f"  Binary Search (iter): {'index ' + str(r2) if r2 != -1 else 'not found'}")
    print(f"  Binary Search (rec):  {'index ' + str(r3) if r3 != -1 else 'not found'}")
    print()

运行该程序将输出

Array: 2 4 6 8 10 12 14 16 18 20

Target 14:
  Linear Search:        index 6
  Binary Search (iter): index 6
  Binary Search (rec):  index 6

Target 15:
  Linear Search:        not found
  Binary Search (iter): not found
  Binary Search (rec):  not found

Target 2:
  Linear Search:        index 0
  Binary Search (iter): index 0
  Binary Search (rec):  index 0

Target 20:
  Linear Search:        index 9
  Binary Search (iter): index 9
  Binary Search (rec):  index 9

Go 实现

package main

import (
    "fmt"
    "strconv"
    "strings"
)

// linear search
func linearSearch(arr []int, target int) int {
    for i := 0; i < len(arr); i++ {
        if arr[i] == target {
            return i
        }
    }
    return -1
}

// binary search (iterative)
func binarySearch(arr []int, target int) int {
    low := 0
    high := len(arr) - 1

    for low <= high {
        mid := low + (high-low)/2
        if arr[mid] == target {
            return mid
        } else if arr[mid] < target {
            low = mid + 1
        } else {
            high = mid - 1
        }
    }
    return -1
}

// binary search (recursive)
func binarySearchRecursive(arr []int, low, high, target int) int {
    if low > high {
        return -1
    }

    mid := low + (high-low)/2

    if arr[mid] == target {
        return mid
    } else if arr[mid] < target {
        return binarySearchRecursive(arr, mid+1, high, target)
    } else {
        return binarySearchRecursive(arr, low, mid-1, target)
    }
}

func formatResult(idx int) string {
    if idx != -1 {
        return "index " + strconv.Itoa(idx)
    }
    return "not found"
}

func main() {
    arr := []int{2, 4, 6, 8, 10, 12, 14, 16, 18, 20}
    targets := []int{14, 15, 2, 20}

    strArr := make([]string, len(arr))
    for i, v := range arr {
        strArr[i] = strconv.Itoa(v)
    }
    fmt.Printf("Array: %s\n\n", strings.Join(strArr, " "))

    for _, t := range targets {
        r1 := linearSearch(arr, t)
        r2 := binarySearch(arr, t)
        r3 := binarySearchRecursive(arr, 0, len(arr)-1, t)

        fmt.Printf("Target %d:\n", t)
        fmt.Printf("  Linear Search:        %s\n", formatResult(r1))
        fmt.Printf("  Binary Search (iter): %s\n", formatResult(r2))
        fmt.Printf("  Binary Search (rec):  %s\n", formatResult(r3))
        fmt.Println()
    }
}

运行该程序将输出

Array: 2 4 6 8 10 12 14 16 18 20

Target 14:
  Linear Search:        index 6
  Binary Search (iter): index 6
  Binary Search (rec):  index 6

Target 15:
  Linear Search:        not found
  Binary Search (iter): not found
  Binary Search (rec):  not found

Target 2:
  Linear Search:        index 0
  Binary Search (iter): index 0
  Binary Search (rec):  index 0

Target 20:
  Linear Search:        index 9
  Binary Search (iter): index 9
  Binary Search (rec):  index 9

三种搜索方法对每个目标的搜索结果完全一致,验证了算法的正确性。对于目标 14,三种方法均返回索引 6;对于不存在的目标 15,均返回"未找到"。边界情况(首元素 2 和末元素 20)也能正确处理。


性能对比

指标 线性搜索 二分搜索(迭代) 二分搜索(递归)
最好时间复杂度 O(1)(第一个元素即为目标) O(1)(中间元素即为目标) O(1)(中间元素即为目标)
平均时间复杂度 O(n) O(log n) O(log n)
最坏时间复杂度 O(n)(目标不存在或在末尾) O(log n) O(log n)
空间复杂度 O(1) O(1) O(log n)(递归调用栈)
前提条件 无(任意数组均可) 数组必须已排序 数组必须已排序
实现难度 简单 中等 中等

何时使用线性搜索

  • 数组未排序,或排序的代价(O(n log n))高于直接搜索。
  • 数组规模很小(例如少于 10 个元素),线性搜索的实际开销可能低于二分搜索。
  • 只需查找第一个匹配项,或需要找到所有匹配项。
  • 数据只搜索一次,不值得预先排序。

何时使用二分搜索

  • 数组已排序且需要多次搜索,二分搜索的高效性会充分体现。
  • 数据规模较大(数千或更多元素),O(log n) 的优势显著。
  • 追求搜索性能,且可以接受排序的预处理开销。
  • 优先选择迭代法实现,因为空间复杂度更低(O(1) vs O(log n)),且不存在栈溢出风险。

数据规模对比

下表展示了不同数据规模下,线性搜索和二分搜索在最坏情况下的比较次数:

数据规模 n 线性搜索(最坏) 二分搜索(最坏)
10 10 4
100 100 7
1,000 1,000 10
1,000,000 1,000,000 20
1,000,000,000 1,000,000,000 30

可以看出,随着数据规模的增长,二分搜索的优势呈指数级扩大。在 10 亿个元素中查找,线性搜索最坏需要 10 亿次比较,而二分搜索仅需 30 次。

posted @ 2026-04-16 11:08  游翔  阅读(15)  评论(0)    收藏  举报