【追求卓越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(amid != value) { if(low >= high) return -1; if(amid > value) high = mid - 1; else if(amid < value) low = mid + 1; mid = low + (high - low)/2; } return mid; } int main() { int a10 = {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(amid > value) high = mid - 1; else if(amid < value) low = mid + 1; else { if(mid==0 || (amid-1 != value)) return mid; else high = mid - 1; } mid = low + (high - low)/2; } return mid; } int main() { int a10 = {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(amid > value) high = mid - 1; else if(amid < value) low = mid + 1; else { if(mid==0 || (amid+1 != value)) return mid; else low = mid + 1; } mid = low + (high - low)/2; } return mid; } int main() { int a10 = {1,5,8,10,15,15,15,18,19,20}; printf("index = %d\n",findlastvalue(a,10,15)); return 0; } |

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

  1. 二分查找依赖于数组

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

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

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

总结

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

相关推荐
Suxing93 分钟前
C语言基础分享:从“租房”到“拆迁”,C语言动态内存管理
java·数据结构·算法
LuminousCPP34 分钟前
单链表专题(四)-刷题复盘篇-LeetCode 138 随机链表复制|原地拷贝法突破复杂指针操作
数据结构·笔记·算法·leetcode·链表
逆境不可逃1 小时前
【LeetCode 912】排序数组——随机化快速排序详解
数据结构·算法·排序算法
Coder-magician1 小时前
《代码随想录》刷题打卡day31:动态规划-背包问题part02
算法·动态规划
薛定e的猫咪1 小时前
从因果视角解决多智能体协作:细读 SCIC 算法
算法
c238561 小时前
《算法武林谱:四大排序神功与二分寻宝术全解》
数据结构·算法·排序算法
一米阳光86611 小时前
软考(中级)软件设计师核心笔记(9)算法——时间复杂度与空间复杂度、查找算法、排序算法
笔记·算法·职场发展·软考·软件设计师·中级职称
OpenApi.cc1 小时前
MoCode — AI Agent Server (Docker) + macOS Desktop Client(开源项目)
数据结构·人工智能·深度学习·神经网络
Mem0rin1 小时前
二分查找:左右边界
数据结构·算法
lazily-c2 小时前
数据结构模板
数据结构