面向对象写二分查找的核心是将数据容器、搜索区间和查找行为拆分为职责清晰的对象。SearchRange封装区间操作,BinarySearcher协调流程,SortedArraySearch在Python中自动排序并提供语义清晰的find方法,提升可读性、复用性与可测试性。

面向对象写二分查找,核心不是把逻辑“套个类壳”,而是把搜索过程中的关键角色——数据容器、搜索区间、查找行为——拆成职责清晰的对象。它让代码更易理解、可复用、好测试,尤其适合初级项目中需要反复调用或后续扩展的场景。
先明确三个核心角色
标准二分查找背后其实有三个稳定实体:
-
有序数据源:比如一个已排序的 int[] 或 List
,它只负责提供元素,不参与逻辑判断 - 搜索区间:封装 left、right、mid 的计算与更新,隐藏下标细节,对外只暴露“当前是否还有范围”“中间值是什么”“如何丢弃左/右半区”
- 查找器(主逻辑):协调前两者,做比较、决定缩哪边、返回结果,不直接操作数组下标
用 Java 写一个干净可复用的版本
下面是一个贴近初级开发习惯的实现,不依赖高级集合,也不做过度抽象:
先定义区间类(职责单一,便于调试):
class SearchRange {
private final int[] data;
private int left;
private int right;
<pre class="brush:php;toolbar:false;">SearchRange(int[] data) {
this.data = data;
this.left = 0;
this.right = data.length - 1;
}
boolean hasElement() {
return left <= right;
}
int midIndex() {
return left + (right - left) / 2; // 防溢出
}
int midValue() {
return data[midIndex()];
}
void discardLeft() {
left = midIndex() + 1;
}
void discardRight() {
right = midIndex() - 1;
}}
再写查找器(专注流程,不碰原始数组):
class BinarySearcher {
public static int search(int[] arr, int target) {
if (arr == null || arr.length == 0) return -1;
<pre class="brush:php;toolbar:false;"> SearchRange range = new SearchRange(arr);
while (range.hasElement()) {
if (range.midValue() == target) {
return range.midIndex();
} else if (range.midValue() < target) {
range.discardLeft();
} else {
range.discardRight();
}
}
return -1;
}}
调用时就很简单:
int[] nums = {2, 5, 8, 13, 21};
int idx = BinarySearcher.search(nums, 13); // 返回 3Python 中更轻量的面向对象写法
Python 不强制封装,但可以用类把“准备+查找”流程组织起来,避免重复写排序和边界检查:
class SortedArraySearch:
def __init__(self, data):
# 确保输入有序,否则主动排序(仅在初始化时做一次)
self.data = sorted(data) if data else []
<pre class="brush:php;toolbar:false;">def find(self, target):
if not self.data:
return -1
left, right = 0, len(self.data) - 1
while left <= right:
mid = left + (right - left) // 2
if self.data[mid] == target:
return mid
elif self.data[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1使用示例
searcher = SortedArraySearch([5, 1, 9, 3]) print(searcher.find(9)) # 输出 3(自动排好序后查找)
这种写法对初学者友好:类名直白、构造时处理脏数据、方法语义清晰,不需要理解“区间对象”也能上手。
为什么这样写更适合初级项目
面向对象不是炫技,是为降低认知负担:
- 不用每次调用都手动初始化 left/right/mid,类帮你记着
- 排序逻辑只出现在构造函数里,后续所有 find() 都基于有序前提,不会漏掉
- 测试时可以单独 mock SearchRange 或替换 SortedArraySearch.data,方便单元验证
- 如果将来要支持降序、支持泛型、加日志或计数,只需改对应类,不影响调用方
只要数组有序、循环条件用 left

















