【追求卓越07】算法--二分查找

引导

经过前面几节排序内容,我们开始接触查找算法--二分查找。

二分查找的时间复杂度是O(logn),是一个非常高效的算法。虽然理解起来很容易,但是真正想要熟练掌握就没那么简单了。

二分查找

二分查找原理:

首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功

这和我们的归并排序,快速排序的思想是不是很相似。

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| include<stdlib.h> #include<stdio.h> #include<string.h> int binarysearch(int a[],int len , int value) { int low = 0; int high = len - 1; int mid = low + (high - low)/2; while(a[mid] != value) { if(low >= high) return -1; if(a[mid] > value) high = mid - 1; else if(a[mid] < value) low = mid + 1; mid = low + (high - low)/2; } return mid; } int main() { int a[10] = {1,5,8,10,13,15,16,18,19,20}; printf("index = %d\n",binarysearch(a,10,16)); return 0; } |

分析:

通过上面代码的实现,我相信大家对二分查找有了一定的了解。但是心细的朋友肯定会发现,这个代码只能确认数组中是否有目标值,若有相同的元素,则不能确定返回第一个。

因此接下来我们再来练习一下二分法的几个变体:

  1. 查找第一个等于给定值的元素
  2. 查找最后一个等于给定值的元素
  3. 查找第一个大于给定值的元素
  4. 查找最后一个小于给定值的元素

其实3,4就是1和2前移或后移的问题,我们主要练习前两个。

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| / *查找第一个等于给定值的元素* / int findfirstvalue(int a[],int len , int value) { int low = 0; int high = len - 1; int mid = low + (high - low)/2; while(1) { if(low > high) return -1; if(a[mid] > value) high = mid - 1; else if(a[mid] < value) low = mid + 1; else { if(mid==0 || (a[mid-1] != value)) return mid; else high = mid - 1; } mid = low + (high - low)/2; } return mid; } int main() { int a[10] = {1,5,8,10,15,15,15,18,19,20}; printf("index = %d\n",findfirstvalue(a,10,15)); return 0; } |

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| / *查找最后一个等于给定值的元素* / int findlastvalue(int a[],int len , int value) { int low = 0; int high = len - 1; int mid = low + (high - low)/2; while(1) { if(low > high) return -1; if(a[mid] > value) high = mid - 1; else if(a[mid] < value) low = mid + 1; else { if(mid==0 || (a[mid+1] != value)) return mid; else low = mid + 1; } mid = low + (high - low)/2; } return mid; } int main() { int a[10] = {1,5,8,10,15,15,15,18,19,20}; printf("index = %d\n",findlastvalue(a,10,15)); return 0; } |

注意:二分查找虽然效率很高但是它受限很多,使用起来也不是很方便,主要有以下几个原因:

  1. 二分查找依赖于数组

我们知道数组在内存中是连续存储的,如果二分查找依赖于数组。这无疑给自己造成很大的局限性。因为当数据量很大时,也就说明需要一个很大的数组,这是一个很高的要求

  1. 二分查找依赖于数据的有序,并且静态

二分查找针对的数据时有序的。当面对的数组时无序的时候该怎么办呢?我们通过之前的排序算法可以知道,排序最快通用的时间复杂度是O(nlogn)。当数组没有频繁的插入删除操作,我们先排序再二分查找,这样也是可以接受的。但是当数组面临常插入和删除的操作时,就不太适用了。会导致事件复杂度上升。

总结

本章我们开始介绍了二分查找,分析了代码实现,以及一些二分查找的变体。也介绍了二分查找适合的场景以及局限性。二分查找依赖有序的数组,对于太大或太小的数组都不太适用(太小没必要,太大没有空间)。并且不适合频繁的数据插入和删除操作。

相关推荐
微笑尅乐5 分钟前
三种思路彻底掌握 BST 判断(递归与迭代全解析)——力扣98.验证二叉搜索树
算法·leetcode·职场和发展
闻缺陷则喜何志丹10 分钟前
【动态规划】数位DP的原理、模板(封装类)
c++·算法·动态规划·原理·模板·数位dp
豆沙沙包?27 分钟前
2025年--Lc194-516. 最长回文子序列(动态规划在字符串的应用,需要二刷)--Java版
java·算法·动态规划
胖咕噜的稞达鸭28 分钟前
二叉树搜索树插入,查找,删除,Key/Value二叉搜索树场景应用+源码实现
c语言·数据结构·c++·算法·gitee
showmethetime29 分钟前
基于相空间重构的混沌时间序列预测MATLAB实现
算法
地平线开发者1 小时前
大模型 | VLM 初识及在自动驾驶场景中的应用
算法·自动驾驶
lingran__1 小时前
算法沉淀第四天(Winner)
c++·算法
AIzealot无1 小时前
Qwen3 Embedding报告随笔
人工智能·深度学习·算法·论文·embedding·论文笔记·搜广推
zzzsde1 小时前
【C++】深入理解string类(5)
java·前端·算法
清风wxy2 小时前
C语言基础数组作业(冒泡算法)
c语言·开发语言·数据结构·c++·windows·算法