数据结构——二分查找法

二分查找法(Binary Search)是一种高效的查找算法,通常用于在已排序的数组或列表中查找特定的目标值。这个算法的基本思想是不断将查找范围缩小为原来的一半,直到找到目标值或确定目标值不存在。

二分查找是一种在每次比较之后将查找空间一分为二的算法。每次需要查找集合中的索引或元素时,都应该考虑二分查找。如果集合是无序的,我们可以总是在应用二分查找之前先对其进行排序。

二分查找一般由三个主要部分组成:
1.预处理一如果集合未排序,则进行排序.
2.二分查找一 使用循环或递归在每次比较后将查找空间划分为两半
3. 后处理在剩余空间中确定可行的候选者

1.二分查找函数 是二分查找的最基础和最基本的形式。这是一个标准的二分查找模板

int binarySearch(const std::vector<int>& arr, int target) {
    int left = 0;
    int right = arr.size() - 1;

    while (left <= right) {
        int mid = left + (right - left) / 2;

        if (arr[mid] == target) {
            return mid; // 找到目标值,返回其索引
        }
        else if (arr[mid] < target) {
            left = mid + 1; // 目标值在右半部分
        }
        else {
            right = mid - 1; // 目标值在左半部分
        }
    }

    return -1; // 目标值不存在
}

2.二分查找函数 是二分查找的高级模板。它用于查找需要访问数组中当前索引及其直接右邻居索引的元素或条件。

int binarySearch(vector<int>& nums, int target) {
    if (nums.size() == 0)
        return -1;

    int left = 0, right = nums.size();

    while (left < right) {
        // Prevent (left + right) overflow
        int mid = left + (right - left) / 2;
        if (nums[mid] == target)
        { 
            return mid;
        }
        else if (nums[mid] < target) 
        { 
            left = mid + 1; 
        }
        else 
        { 
            right = mid; 
        }
    }

    // Post-processing:
    // End Condition: left == right
    if (left != nums.size() && nums[left] == target) 
        return left;

    return -1;
}

3.二分查找函数 是二分查找的另一种独特形式。 它用于搜索需要访问当前索引及其在数组中的直接左右邻居索引的元素或条件。

int binarySearch3(vector<int>& nums, int target) {
    if (nums.size() == 0)
        return -1;

    int left = 0, right = nums.size() - 1;
    while (left + 1 < right) {
        // Prevent (left + right) overflow
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) 
        {
            return mid;
        }
        else if (nums[mid] < target)
        {
            left = mid;
        }
        else
        {
            right = mid;
        }
    }

    // Post-processing:
    // End Condition: left + 1 == right
    if (nums[left] == target)
        return left;

    if (nums[right] == target)
        return right;

    return -1;
}
### 二分查找法的平均搜索长度(ASL) 对于有序数组中的二分查找算法,其平均搜索长度(ASL)可以通过概率论来计算。当在一个含有 \( n \) 个元素的有序列表中执行二分查找时,每次比较都将当前区间分为两部分,直到找到目标值或确认不存在该值为止。 设 Pi 表示成功定位到第 i 个位置上的记录的概率;Ci 则表示实际发生这种情况下的比较次数,则有: \[ ASL=\sum_{i=1}^{n}{P_iC_i}\quad(0\leq P_i\leq1,\sum{P_i}=1)\tag{1} \] 在理想情况下,如果所有元素被访问的可能性相等,即 \( P_1=P_2=...=P_n=\frac{1}{n} \),此时可以简化上述表达式为: \[ C_i=log_2(i+1)+log_2(n-i+1)-1\approx log_2n \] 因此,在最坏情况下的时间复杂度大约等于 O(log₂n)[^2]。然而这并不完全适用于描述整个过程中的期望比较次数——也就是所谓的“平均搜索长度”。 为了更精确地给出 ASL 的具体数值,考虑如下推导方式:假定我们有一个大小为 N 的已排序数组,并且要从中随机选取某个整数作为查询对象。因为是均匀分布,所以每个索引处的数据项都有相同的选中几率 p = 1/N 。而每一次成功的匹配都需要经历若干轮迭代才能最终锁定确切的位置 k ,这些可能发生在任何一层递归调用之中。于是乎我们可以得到下面这个公式用于估算 ASL : \[ ASL ≈ \int _ { 0 } ^ { H } h d F(h)=H-\sum _ { j = 0 } ^ { H }\left(\frac{1}{2}\right)^j \] 这里 H 是树的高度,F(h)代表高度不超过h节点的比例。经过进一步化简可得近似解: \[ ASL≈ln⁡N+\gamma , (\gamma≈0.577 )\] 这意味着随着输入规模增大,二分查找所需的预期比较次数会逐渐趋近于自然对数 ln(N) 加上欧拉常量 γ (约为 0.577)。这种渐进性质反映了二分查找效率高的特点之一。 ```python import math def calculate_asl_binary_search(n): gamma = 0.577 asl = math.log(n) + gamma return round(asl, 4) # Example usage with an array of size 8 elements. print(f"The estimated Average Search Length for binary search on a list of length 8 is approximately {calculate_asl_binary_search(8)} comparisons.") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值