【计算机科学的数学基础】二分法查找

问题引入

问:有15个犯罪嫌疑人排成一排,其中只有1个是真正的“犯人”。你要通过问他们“犯人在哪里?”来找出真正的犯人。没问一次问题都会得到以下3种答案:

  1. 我是犯人
  2. 犯人在我左边
  3. 犯人在我右边

如何仅通过3次文化,就找到真正的犯人?

解:每次都从中间提问,然后根据回答剩下一半的人,接着再从剩下的一半的中间开始问。这样第1次问完后,就可以筛选出7人,第2次提问后,筛选出3人,第3次提问后,就可以锁定1人了。

将该问题推广,“通过 n n n次提问,最多能从多少人中锁定犯人”,假设嫌疑人总人数为 P ( n ) P(n) P(n)
P ( n ) = { 1 , ( n = 0 ) P ( n − 1 ) + 1 + P ( n − 1 ) , ( n = 1 , 2 , 3 , ⋯   ) P(n)=\begin{cases} 1, & (n=0) \\ P(n-1)+1+P(n-1), & (n=1,2,3,\cdots) \end{cases} P(n)={1,P(n1)+1+P(n1),(n=0)(n=1,2,3,)
或者
P ( n ) = 2 n + 1 − 1 P(n)=2^{n+1}-1 P(n)=2n+11

这种从有序数据中找出目标数据时总是判断秒数据所在范围内正中间数据的方法,叫作“二分法”或“二分查找”。
它能以指数的速度减低查找的次数。

在有序数列中查找

现在将情景转变到在计算机中查找数据:

问:在下面从小到大排列的15个数中,查找出67的位置。
16 , 17 , 23 , 29 , 31 , 42 , 45 , 58 , 62 , 66 , 67 , 71 , 78 , 83 , 88 16,17,23,29,31,42,45,58,62,66,67,71,78,83,88 16,17,23,29,31,42,45,58,62,66,67,71,78,83,88

二分法查找的代码(C++ 20)如下:

import <iostream>;
import <vector>;
import <format>;

using namespace std;

int main()
{
	vector<int> arr{ 16, 17, 23, 29, 31, 42, 45, 58, 62, 66, 67, 71, 78, 83, 88 };
	
	int size{ static_cast<int>(arr.size()) / 2 };
	const int obj{ 67 };
	while (arr.at(size) != obj) {//如果中间不是
		if (arr.at(size) > obj) {//如果在左边
			size = size / 2;
		}
		else if (arr.at(size) < obj) {//如果在右边
			size = (15 + size) / 2;
		}
	}
	cout << "=====二分法查找=====" << endl;
	cout << "在以下数组中:" << endl;
	for (auto arr : arr) {
		cout << arr << "; ";
	}
	cout << endl;
	cout << format("{}位于数组的第{}位", obj, size+1) << endl;
}

输出结果如下:
二分法查找结果

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值