【追求卓越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)。当数组没有频繁的插入删除操作,我们先排序再二分查找,这样也是可以接受的。但是当数组面临常插入和删除的操作时,就不太适用了。会导致事件复杂度上升。

总结

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

相关推荐
我想进大厂36 分钟前
图论---朴素Prim(稠密图)
数据结构·c++·算法·图论
我想进大厂41 分钟前
图论---Bellman-Ford算法
数据结构·c++·算法·图论
AIGC大时代43 分钟前
高效使用DeepSeek对“情境+ 对象 +问题“型课题进行开题!
数据库·人工智能·算法·aigc·智能写作·deepseek
lkbhua莱克瓦241 小时前
用C语言实现——一个中缀表达式的计算器。支持用户输入和动画演示过程。
c语言·开发语言·数据结构·链表·学习方法·交友·计算器
CODE_RabbitV1 小时前
【深度强化学习 DRL 快速实践】近端策略优化 (PPO)
算法
Wendy_robot2 小时前
【滑动窗口+哈希表/数组记录】Leetcode 438. 找到字符串中所有字母异位词
c++·算法·leetcode
程序员-King.2 小时前
day49—双指针+贪心—验证回文串(LeetCode-680)
算法·leetcode·贪心算法·双指针
转基因3 小时前
Codeforces Round 1020 (Div. 3)(题解ABCDEF)
数据结构·c++·算法
Forworder4 小时前
[数据结构]树和二叉树
java·数据结构·intellij-idea·idea
我想进大厂4 小时前
图论---Kruskal(稀疏图)
数据结构·c++·算法·图论