C++ 的 ranges 和 Python 的 bisect 在二分查找中的应用与实现

这篇文章将介绍 C++ 的 rangesPython 的 bisect 在二分查找中的应用与实现,并附上完整示例代码。


二分查找简介

二分查找(Binary Search)是一种高效搜索算法,用于在有序序列中快速定位目标值。它的时间复杂度为 O(log n),比线性搜索快得多。

在现代编程语言中,很多标准库都封装了二分查找逻辑,不必手写算法。例如:

  • C++20 提供了 std::ranges 系列算法(如 ranges::binary_search, ranges::lower_bound 等)
  • Python 提供了 bisect 模块(如 bisect_left, bisect_right

一、C++中的 std::ranges

1. 基本概念

std::ranges 是 C++20 引入的新特性,将算法与范围结合,代码更简洁、类型更安全。

常用的二分查找相关函数:

  • std::ranges::binary_search(range, value):检查 value 是否存在于有序范围中
  • std::ranges::lower_bound(range, value):返回第一个 不小于 value 的位置
  • std::ranges::upper_bound(range, value):返回第一个 大于 value 的位置

注意:这些函数要求范围已按升序排序,否则结果不正确。


2. 示例代码(C++20)

cpp 复制代码
#include <iostream>
#include <vector>
#include <algorithm>
#include <ranges>  // C++20 ranges 头文件

int main() {
    std::vector<int> data = {1, 3, 5, 7, 9, 11, 13};

    // 使用 ranges::binary_search 判断值是否存在
    if (std::ranges::binary_search(data, 7)) {
        std::cout << "Found 7 in data.\n";
    } else {
        std::cout << "7 not found.\n";
    }

    // lower_bound:找到第一个 >= 6 的元素位置
    auto lb_it = std::ranges::lower_bound(data, 6);
    if (lb_it != data.end()) {
        std::cout << "Lower bound for 6 is: " << *lb_it << "\n";
    } else {
        std::cout << "No element >= 6 found.\n";
    }

    // upper_bound:找到第一个 > 7 的元素
    auto ub_it = std::ranges::upper_bound(data, 7);
    if (ub_it != data.end()) {
        std::cout << "Upper bound for 7 is: " << *ub_it << "\n";
    } else {
        std::cout << "No element > 7 found.\n";
    }

    return 0;
}

运行结果:

复制代码
Found 7 in data.
Lower bound for 6 is: 7
Upper bound for 7 is: 9

二、Python中的 bisect 模块

1. 基本概念

Python 的 bisect 模块提供了二分查找与排序插入位置计算的功能,常用函数:

  • bisect.bisect_left(a, x):返回 x 应插入 到列表 a 中的位置,保持排序,偏向左边
  • bisect.bisect_right(a, x):返回 x 的插入位置,偏向右边(即在现有 equal 元素后插入)
  • bisect.insort(a, x) / insort_left:直接按排序插入元素

2. 示例代码(Python)

python 复制代码
import bisect

data = [1, 3, 5, 7, 9, 11, 13]

# 检查元素是否存在(通过 bisect_left)
x = 7
idx = bisect.bisect_left(data, x)
if idx < len(data) and data[idx] == x:
    print(f"Found {x} at index {idx}.")
else:
    print(f"{x} not found.")

# lower_bound 类似实现
lb_idx = bisect.bisect_left(data, 6)
if lb_idx < len(data):
    print(f"Lower bound for 6 is: {data[lb_idx]}")
else:
    print("No element >= 6 found.")

# upper_bound 类似实现
ub_idx = bisect.bisect_right(data, 7)
if ub_idx < len(data):
    print(f"Upper bound for 7 is: {data[ub_idx]}")
else:
    print("No element > 7 found.")

运行结果:

复制代码
Found 7 at index 3.
Lower bound for 6 is: 7
Upper bound for 7 is: 9

三、C++与Python的对比

特性 C++ ranges Python bisect
引入版本 C++20 Python标准库(一直存在)
API命名风格 binary_search, lower_bound, upper_bound bisect_left, bisect_right
是否返回迭代器/索引 返回迭代器 返回索引
插入功能 需手动使用 vector.insert insort 系列直接插入
性能 编译期优化,更高效 运行时动态,适合快速原型

四、应用场景

  • 查找范围内元素的位置
  • 求某一值的上下界
  • 避免在大数据中手动写二分查找
  • 保持有序列表插入新元素

例如:

  • 排行榜排名确定
  • 时间序列中快速定位某个时间点
  • 财务数据中找某个价格区间的交易记录

总结

在 C++ 中使用 std::ranges 能让二分查找更简洁、类型安全,并支持各种范围类型;在 Python 中,bisect 模块对于保持列表有序和快速检索位置非常方便。两者在概念上类似,但 Python 返回索引,C++ 返回迭代器/布尔值,因此在使用时需要注意差异。

相关推荐
枫叶林FYL6 分钟前
【自然语言处理 NLP】8.3 长文本推理评估与针在大海堆任务
人工智能·算法
智者知已应修善业8 分钟前
【51单片机1,左边4个LED灯先闪烁2次后,右边4个LED灯再闪烁2次:2,接着所用灯一起闪烁3次,接着重复步骤1,如此循环。】2023-5-19
c++·经验分享·笔记·算法·51单片机
小白学大数据10 分钟前
告别复杂 XPath:DeepSeek+Python 爬虫快速实践
开发语言·爬虫·python·selenium
xiaoye-duck14 分钟前
《算法题讲解指南:优选算法-队列+宽搜》--70.N叉树的层序遍历,71.二叉树的锯齿形层序遍历,72.二叉树的最大宽度,73.在每个树行中找最大值
数据结构·c++·算法·队列
代码改善世界15 分钟前
【C++初阶】双向循环链表:List底层结构的完整实现剖析
c++·链表·list
汀、人工智能16 分钟前
[特殊字符] 第98课:数据流中位数
数据结构·算法·数据库架构··数据流·数据流中位数
AI_Claude_code18 分钟前
ZLibrary访问困境方案六:自建RSS/Calibre内容同步服务器的完整指南
运维·服务器·网络·爬虫·python·tcp/ip·http
REDcker19 分钟前
C++ 包管理工具概览
开发语言·c++
Eloudy19 分钟前
不同特征值的特征向量互相正交的矩阵
人工智能·算法·机器学习
weixin_4620223521 分钟前
Dancing under the stars: video denoising in starlight
python·计算机视觉