二分查找算法详解

合集下载

二分查找算法 经典题

二分查找算法 经典题

二分查找算法经典题一、二分查找算法简介二分查找(Binary Search)是一种在有序数组中查找特定元素的搜索算法。

相较于全序查找,二分查找能够在时间复杂度上实现O(log n)的高效搜索。

该算法基于比较思想,通过不断缩小搜索范围来找到目标元素。

二、二分查找算法的应用场景1.有序数组查找:当数据集已经有序时,使用二分查找可以获得较快的搜索速度。

2.区间查找:在给定一个区间,寻找区间内的特定元素,如最大值、最小值等。

3.有序树查找:在二叉搜索树(BST)中进行查找操作。

三、经典二分查找题目解析1.题目一:有序数组查找特定元素给定一个有序数组,实现一个二分查找函数,找到目标元素的位置。

2.题目二:区间查找给定一个有序数组和一个小于数组平均值的值,找到该值在数组中的位置。

3.题目三:有序链表查找给定一个有序链表,实现一个二分查找函数,找到目标元素的位置。

四、实战案例与代码演示以下是一个使用Python实现的二分查找算法示例:```pythondef binary_search(arr, target):left, right = 0, len(arr) - 1while left <= right:mid = left + (right - left) // 2if arr[mid] == target:return midelif arr[mid] < target:left = mid + 1else:right = mid - 1return -1arr = [1, 3, 5, 7, 9, 11, 13, 15]target = 11print(binary_search(arr, target)) # 输出:4```五、优化与扩展1.线性时间复杂度优化:当数据集无序时,可以通过预处理数据实现有序化,从而将时间复杂度降低到O(n)。

2.外部排序:当数据集过大,无法一次性加载到内存中时,可以通过外部排序实现二分查找。

C++ 二分法查找

C++ 二分法查找

二分法查找1、二分查找(Binary Search)二分查找又称折半查找,它是一种效率较高的查找方法。

二分查找要求:线性表是有序表,即表中结点按关键字有序,并且要用向量作为表的存储结构。

不妨设有序表是递增有序的。

2、二分查找的基本思想二分查找的基本思想是:(设R[low..high]是当前的查找区间)(1)首先确定该区间的中点位置:(2)然后将待查的K值与R[mid].key比较:若相等,则查找成功并返回此位置,否则须确定新的查找区间,继续二分查找,具体方法如下:①若R[mid].key>K,则由表的有序性可知R[mid..n].keys均大于K,因此若表中存在关键字等于K的结点,则该结点必定是在位置mid左边的子表R[1..mid-1]中,故新的查找区间是左子表R[1..mid-1]。

②类似地,若R[mid].key<K,则要查找的K必在mid的右子表R[mid+1..n]中,即新的查找区间是右子表R[mid+1..n]。

下一次查找是针对新的查找区间进行的。

因此,从初始的查找区间R[1..n]开始,每经过一次与当前查找区间的中点位置上的结点关键字的比较,就可确定查找是否成功,不成功则当前的查找区间就缩小一半。

这一过程重复直至找到关键字为K的结点,或者直至当前的查找区间为空(即查找失败)时为止。

3、二分查找算法int BinSearch(SeqList R,KeyType K){ //在有序表R[1..n]中进行二分查找,成功时返回结点的位置,失败时返回零int low=1,high=n,mid;//置当前查找区间上、下界的初值while(low<=high){ //当前查找区间R[low..high]非空mid=(low+high)/2;if(R[mid].key==K) return mid;//查找成功返回if(R[mid].kdy>K)high=mid-1; //继续在R[low..mid-1]中查找elselow=mid+1;//继续在R[mid+1..high]中查找}return 0;//当low>high时表示查找区间为空,查找失败} //BinSeareh二分查找算法亦很容易给出其递归程序【参见练习】4、二分查找算法的执行过程设算法的输入实例中有序的关键字序列为(05,13,19,21,37,56,64,75,80,88,92)要查找的关键字K分别是21和85。

2分查找算法

2分查找算法

2分查找算法二分查找算法,也称为折半查找算法,是计算机科学中一种常用的查找算法。

它的核心思想是将待查找的数据集合分成两半,然后通过与目标值的比较,确定目标值可能存在的范围,再逐步缩小范围,直到找到目标值或确定目标值不存在。

二分查找算法适用于有序的数据集合,可以快速定位目标值的位置,时间复杂度为O(logn)。

下面以二分查找算法为中心,详细阐述其原理和应用。

一、算法原理二分查找算法的原理非常简单,主要包含以下几个步骤:1.确定查找范围:将待查找的数据集合按照升序或降序排列,并确定查找范围的起始位置和结束位置。

2.计算中间位置:通过起始位置和结束位置计算出中间位置。

3.比较目标值:将目标值与中间位置的值进行比较。

-如果目标值等于中间位置的值,则查找成功,返回中间位置。

-如果目标值小于中间位置的值,则目标值可能在前半部分,将查找范围缩小到前半部分。

-如果目标值大于中间位置的值,则目标值可能在后半部分,将查找范围缩小到后半部分。

4.缩小查找范围:根据比较结果,缩小查找范围为前半部分或后半部分,并重复步骤2和步骤3,直到找到目标值或确定目标值不存在。

二、算法示例为了更好地理解二分查找算法,我们以一个具体的例子来说明:假设有一个按升序排列的数组[1,3,5,7,9,11,13,15,17, 19],我们要查找目标值为9的位置。

1.确定查找范围:起始位置为0,结束位置为9。

2.计算中间位置:(0+9)/2=4,中间位置为4。

3.比较目标值:目标值9大于中间位置的值7,所以目标值可能在后半部分。

4.缩小查找范围:将查找范围缩小到[9,11,13,15,17,19],起始位置更新为中间位置+1=5,结束位置不变。

5.重复步骤2和步骤3:计算新的中间位置(5+9)/2=7,中间位置为7。

目标值9小于中间位置的值15,所以目标值可能在前半部分。

6.缩小查找范围:将查找范围缩小到[9,11,13],起始位置更新为5,结束位置更新为中间位置-1=6。

二分算法详解

二分算法详解

二分算法详解二分算法,也称为二分查找,是一种常用的查找算法。

它的基本思想是将待查找的区间不断二分,缩小查找范围,直到找到目标元素或确定目标元素不存在。

二分算法的思路相对简单,但在实际应用中却有着广泛的用途。

它适用于有序数组或有序列表,能够快速定位目标元素的位置。

接下来,我们将详细介绍二分算法的具体实现过程。

我们需要确定待查找的有序数组或有序列表。

假设我们要查找的元素存储在一个升序排列的数组中。

为了方便描述,我们假设数组名为arr,长度为n。

接下来,我们需要确定目标元素的值,假设为target。

接下来,我们需要定义两个指针,分别指向待查找区间的起始位置和结束位置。

初始时,起始位置指向数组的第一个元素,结束位置指向数组的最后一个元素。

假设起始位置的索引为low,结束位置的索引为high。

接下来,我们需要进行迭代查找。

在每次迭代中,我们需要计算待查找区间的中间位置。

假设中间位置的索引为mid,计算方法为mid = (low + high) / 2。

然后,我们需要比较中间位置的元素与目标元素的大小关系。

如果中间位置的元素等于目标元素,说明我们已经找到了目标元素,算法结束。

如果中间位置的元素大于目标元素,说明目标元素可能在中间位置的左侧,我们将结束位置移到中间位置的前一个位置,即high = mid - 1。

如果中间位置的元素小于目标元素,说明目标元素可能在中间位置的右侧,我们将起始位置移到中间位置的后一个位置,即low = mid + 1。

然后,我们需要判断迭代是否结束。

如果起始位置大于结束位置,说明目标元素不存在于数组中,算法结束。

如果起始位置小于等于结束位置,说明目标元素可能存在于数组中的某个位置,我们需要继续迭代查找。

通过以上迭代过程,我们可以在有序数组中快速定位目标元素的位置。

二分算法的时间复杂度为O(logn),其中n为数组的长度。

相比于线性查找算法的时间复杂度O(n),二分算法的效率更高。

除了在查找中的应用,二分算法还可以用于其他问题的解决。

二分法解决问题实例及解答过程

二分法解决问题实例及解答过程

二分法解决问题实例及解答过程二分法,又称折半查找,是一种在有序数组中查找特定元素的方法。

它的原理是将数组中的数据按照某种顺序排列,然后每次查找时都将待查找的数据与数组中间的元素进行比较,逐步缩小查找范围,直到找到目标元素为止。

二分法的时间复杂度为O(log n),效率极高,在应对大量数据的查找时能够快速定位目标元素。

下面就用一个实际的问题来演示二分法的应用过程。

假设有一个有序数组arr,里面存储了一些数值,我们要在arr中查找目标值target,如果找到了就返回其索引,找不到就返回-1。

1.首先,我们要确定二分法的查找范围,即左边界和右边界。

在开始时,左边界为0,右边界为数组的长度减一。

2.接下来就是进入循环,不断进行比较和缩小查找范围的过程。

具体步骤如下:-计算中间元素的索引mid:mid = (left + right) / 2,取整数部分。

-比较中间元素和目标值的大小:-如果中间元素等于目标值,返回mid;-如果中间元素大于目标值,缩小查找范围:right = mid - 1;-如果中间元素小于目标值,缩小查找范围:left = mid + 1。

3.循环直到left大于right,这时表示已经查找完整个数组,依然没有找到目标值,返回-1。

下面我们用一个具体的例子来演示。

假设有一个有序数组arr = [1, 3, 5, 7, 9, 11, 13, 15],要在arr中查找目标值为9。

首先,初始化左右边界:left = 0right = 7进入循环:1.第一轮循环:-计算中间元素的索引:mid = (0 + 7) / 2 = 3- arr[mid] = 7,小于目标值9,所以更新左边界:left = mid +1 = 42.第二轮循环:-计算中间元素的索引:mid = (4 + 7) / 2 = 5- arr[mid] = 11,大于目标值9,所以更新右边界:right = mid - 1 = 43.第三轮循环:-计算中间元素的索引:mid = (4 + 4) / 2 = 4- arr[mid] = 9,等于目标值9,找到目标值,返回mid。

C语言二分查找算法及实现代码

C语言二分查找算法及实现代码

C语言二分查找算法及实现代码二分查找算法,又称折半查找算法,是一种效率很高的查找算法。

该算法通过将待查找的元素与已知的中间元素进行比较,从而确定待查找元素在左半部分还是右半部分,接着再将待查找元素与新的中间元素进行比较,继续确定待查找元素在左半部分还是右半部分,如此递归循环,直到找到待查找元素或确定该元素不存在为止。

二分查找算法的前提条件是待查找的数组或有序表必须是有序的。

下面是C语言的二分查找算法的实现代码:```c#include <stdio.h>int binarySearch(int arr[], int target, int left, int right) if (left <= right)int mid = left + (right - left) / 2;if (arr[mid] == target)return mid;} else if (arr[mid] < target)return binarySearch(arr, target, mid + 1, right);} elsereturn binarySearch(arr, target, left, mid - 1);}}return -1;int maiint arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};int n = sizeof(arr) / sizeof(arr[0]);int target = 6;int result = binarySearch(arr, target, 0, n - 1);if (result == -1)printf("Element not found in array.\n");} elseprintf("Element found at index %d.\n", result);}return 0;```以上代码实现了一个二分查找算法的例子。

二分查找原理

二分查找原理

二分查找原理在计算机科学中,二分查找是一种常见的算法,也被称为折半查找。

它是一种基于分治思想的算法,用于在有序数组中查找特定元素的位置。

它的时间复杂度为O(log n),使得它成为一种非常高效的搜索算法。

二分查找的基本原理是将目标值与数组中间位置的元素进行比较。

如果目标值小于中间位置的元素,则在数组的左半部分继续查找;如果目标值大于中间位置的元素,则在数组的右半部分继续查找。

通过不断缩小查找范围,最终可以找到目标值在数组中的位置。

二分查找的实现可以采用递归或迭代的方式。

下面是一个简单的递归实现:```int binarySearch(int arr[], int left, int right, int target) {if (right >= left) {int mid = left + (right - left) / 2;if (arr[mid] == target) {return mid;}if (arr[mid] > target) {return binarySearch(arr, left, mid - 1, target);}return binarySearch(arr, mid + 1, right, target);}return -1;}```在这个实现中,left和right分别表示数组的左右边界,target 是要查找的目标值。

如果目标值等于中间位置的元素,则返回中间位置的下标。

如果目标值小于中间位置的元素,则在左半部分继续查找;如果目标值大于中间位置的元素,则在右半部分继续查找。

如果没有找到目标值,则返回-1。

二分查找的优点是它的时间复杂度非常低,只需要O(log n)的时间就可以完成查找。

这使得它在处理大型数据集时非常高效。

它还可以应用于各种不同的数据类型,包括数字、字符串、日期等。

然而,二分查找也有一些局限性。

首先,它只适用于有序数组。

如果数组是无序的,则需要先对数组进行排序,这会增加时间复杂度。

生活中的二分查找算法

生活中的二分查找算法

二分查找算法是一种在有序数组中查找特定元素的高效算法。

在生活中,我们可以将二分查找算法应用于许多场景,以提高搜索效率。

以下是一些例子:
1. 字典查找:当我们使用字典查找一个单词的定义时,通常会从中间的页码开始查找。

如果所查找的单词在中间页码之前,则在字典的前半部分查找;如果在中间页码之后,则在字典的后半部分查找。

这种查找方式就是应用了二分查找算法。

2. 电话簿搜索:在电话簿中查找一个联系人时,我们可以先大致估计联系人姓名所在的位置,然后根据估计的位置进行查找。

如果找到了联系人,则搜索成功;如果没有找到,则根据姓名首字母在电话簿中的位置,判断联系人可能在前面或后面的部分,然后相应地缩小搜索范围。

这也是二分查找的一种应用。

3. 有序数据库查询:在数据库管理中,当我们需要根据特定关键字查询数据时,如果数据库中的数据是有序的,我们可以使用二分查找算法来加快查询速度。

例如,在电子商务网站中根据价格排序的商品列表中查找特定价格的商品。

4. 软件更新:在软件更新过程中,有时我们需要根据特定条件(如版本号)在大量更新文件中查找对应的更新包。

通过使用二分查找算法,我们可以快速定位到所需的更新文件,从而提高更新效率。

5. 排序比赛:在某些排序比赛中,参赛者需要根据特定的规则对一系列数据进行排序。

在这种情况下,参赛者可以使用二分查找算法来确定自己的排名,从而节省时间并提高效率。

总之,二分查找算法在生活中的许多场景中都有应用,它可以帮助我们更快地找到所需的信息,提高工作和生活的效率。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

二分查找算法详解二分查找算法,是一种在有序数组中查找某一特定元素的搜索算法。

注意两点:(1)有序:查找之前元素必须是有序的,可以是数字值有序,也可以是字典序。

为什么必须有序呢?如果部分有序或循环有序可以吗?(2)数组:所有逻辑相邻的元素在物理存储上也是相邻的,确保可以随机存取。

算法思想:搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。

如果在某一步骤数组为空,则代表找不到。

这种搜索算法每一次比较都使搜索范围缩小一半。

这里我们可以看到:(1) 如果查找值和中间值不相等的时候,我们可以确保可以下次的搜索范围可以缩小一半,正是由于所有元素都是有序的这一先决条件(2) 我们每次查找的范围都是理应包含查找值的区间,当搜索停止时,如果仍未查找到,那么此时的搜索位置就应该是查找值应该处于的位置,只是该值不在数组中而已算法实现及各种变形:1. 非降序数组A, 查找任一个值==val的元素,若找到则返回下标位置,若未找到则返回-12. 非降序数组A, 查找第一个值==val的元素,若找到则返回下标位置,若未找到则返回-1 (类似:查找数组中元素最后一个小于val 值的位置)3. 非降序数组A, 查找最后一个值==val的元素,若找到则返回下标位置,若未找到则返回-1 (类似:查找数组中元素第一个大于val 值的位置)4. 非降序数组A, 查找任一值为val的元素,保证插入该元素后数组仍然有序,返回可以插入的任一位置5. 非降序数组A, 查找任一值为val的元素,保证插入该元素后数组仍然有序,返回可以插入的第一个位置6. 非降序数组A, 查找任一值为val的元素,保证插入该元素后数组仍然有序,返回可以插入的最后一个位置7. 非降序数组A, 查找任一个值==val的元素,若找到则返回一组下标区间(该区间所有值==val),若未找到则返回-18. 非降序字符串数组A, 查找任一个值==val的元素,若找到则返回下标位置,若未找到则返回-1(类似:未找到时返回应该插入点)9. 循环有序数组中查找== val 的元素,若找到则返回下标位置,若未找到则返回-11. 非降序数组A, 查找任一个值==val的元素,若找到则返回下标位置,若未找到则返回-11 int binary_search(int* a, int len, int val)2 {3 assert(a != NULL && len > 0);4 int low = 0;5 int high = len - 1;6 while (low <= high) {7 int mid = low + (high - low) / 2;8 if (val < a[mid]) {9 high = mid - 1;10 } else if (val > a[mid]) {11 low = mid + 1;12 } else {13 return mid;14 }15 }16 return -1;17 }注意:(1) 使用assert对函数输入进行合法性检查(2) while 循环的条件是low<=high,这里如果查找值未找到,则此时一定low = high + 1(3) 对val 和a[mid] 做比较时,首先考虑不等情况,最后考虑相等情况,如果随机分布的话不等的概率肯定大于相等的概率2. 非降序数组A, 查找第一个值==val的元素,若找到则返回下标位置,若未找到则返回-1 (类似:查找数组中元素最后一个小于val 值的位置)因为数组中可能有重复元素,所以数组中是有可能存在多个值与val 相等的,我们对普通二分进行变形:当val < a[mid] 时,接下来的搜索范围减半 high = mid - 1当val > a[mid] 时,接下来的搜索范围减半 low = mid + 1当val == a[mid] 时,这个时候就不能简单的返回了,我们要求的是第一个== val 的值,什么条件下是第一个呢?当mid == 0 那当然是第一个当mid > 1 && a[mid - 1] != val 这个时候也是第一个其他情况下,这个时候查找到的值不是第一个,此时我们应该继续搜索,而不是返回,搜索范围是什么呢?因为是查找第一个,那么接下来肯定应该在此时位置的左边继续搜索,即high = mid - 11 int search_first(int* a, int len, int val)2 {3 assert(a != NULL && len > 1);4 int low = 0;5 int high = len - 1;6 while (low <= high) {7 int mid = low + (high - low) / 2;8 if (val < a[mid]) {9 high = mid - 1;10 } else if (val > a[mid]) {11 low = mid + 1;12 } else {13 if (mid == 0) return mid;14 if (mid > 0 && a[mid-1] != val) return mid;15 high = mid - 1;16 }17 }18 return -1;19 }3. 非降序数组A, 查找最后一个值==val的元素,若找到则返回下标位置,若未找到则返回-1 (类似:查找数组中元素第一个大于val 值的位置)算法思想与第2题相同1 int search_last(int* a, int len, int val)2 {3 assert(a != NULL && len > 1);4 int low = 0;5 int high = len - 1;6 while (low <= high) {7 int mid = low + (high - low) / 2;8 if (val < a[mid]) {9 high = mid - 1;10 } else if (val > a[mid]) {11 low = mid + 1;12 } else {13 if (mid == (len - 1)) return mid;14 if (mid < (len - 1) && a[mid+1] != val) return mid;15 low = mid + 1;16 }17 }18 return -1;19 }4. 非降序数组A, 查找任一值为val的元素,保证插入该元素后数组仍然有序,返回可以插入的任一位置当a[mid] == val 则返回mid,因为在该位置插入val 数组一定保证有序当循环结束后仍未查找到val值,我们之前说过,此时一定有high = low + 1,其实查找值永远都应该在low和high组成的区间内,现在区间内没空位了,所以可以宣告该值没有查找到,如果仍然有空位,则val一定在该区间内。

也就是说此时的low 和high 这两个值就是val 应该处于的位置,因为通常都是在位置之前插入,所以此时直接返回low 即可1 int insert(int* a, int len, int val)2 {3 assert(a != NULL && len > 0);4 int low = 0;5 int high = len - 1;6 while (low <= high) {7 int mid = low + (high - low) / 2;8 if (val < a[mid]) {10 } else if (val > a[mid]) {11 low = mid + 1;12 } else {13 return mid;14 }15 }16 return low;17 }5. 非降序数组A, 查找任一值为val的元素,保证插入该元素后数组仍然有序,返回可以插入的第一个位置因为是要求第一个可以插入的位置,当查找值不在数组中时,插入的位置是唯一的,即return low当查找值出现在数组中时,此时就演变成了查找第一个== val 的值,详见第2题1 int insert_first(int* a, int len, int val)2 {3 assert(a != NULL && len > 1);4 int low = 0;5 int high = len - 1;6 while (low <= high) {7 int mid = low + (high - low) / 2;8 if (val < a[mid]) {9 high = mid - 1;10 } else if (val > a[mid]) {11 low = mid + 1;12 } else {13 if (mid == 0) return mid;14 if (mid > 0 && a[mid-1] != val) return mid;15 high = mid - 1;16 }17 }18 return low;19 }6. 非降序数组A, 查找任一值为val的元素,保证插入该元素后数组仍然有序,返回可以插入的最后一个位置算法思想与第5 题相同1 int insert_last(int* a, int len, int val)2 {3 assert(a != NULL && len > 1);4 int low = 0;5 int high = len - 1;6 while (low <= high) {7 int mid = low + (high - low) / 2;8 if (val < a[mid]) {10 } else if (val > a[mid]) {11 low = mid + 1;12 } else {13 if (mid == (len - 1)) return mid;14 if (mid < (len - 1) && a[mid+1] != val) return mid;15 low = mid + 1;16 }17 }18 return low;19 }7. 非降序数组A, 查找任一个值==val的元素,若找到则返回一组下标区间(该区间所有值==val),若未找到则返回-1我们首先想到的是根据第1 题进行稍微修改,当a[mid] == val 时,并不立即return mid,而是以mid 为中心向左右两边搜索得到所有值== val 的区间注意此算法时间复杂度可能O(n) 当数组中所有值都等于val时,此算法的复杂度为O(n)联想到第2 题和第 3 题,我们可以首先找到一个== val 的下标,然后找到最后一个== val 的下标,两下标即为所求,此时,算法复杂度为2*log(n) 为最优方法具体算法实现此处略去8. 非降序字符串数组A, 查找任一个值==val的元素,若找到则返回下标位置,若未找到则返回-1(类似:未找到时返回应该插入点)注意我们这是字符串数组,其实这和第 1 题基本相同,只是元素做比较时对象时字符串而已1 int binary_search(char* a[], int len, char* val)2 {3 assert(a != NULL && len > 0 && val != NULL);4 int low = 0;5 int high = len - 1;6 while (low <= high) {7 int mid = low + (high - low) / 2;8 if (strcmp(val, a[mid]) < 0) {9 high = mid - 1;10 } else if (strcmp(val, a[mid]) > 0) {11 low = mid + 1;12 } else {13 return mid;14 }15 }16 return -1; // or return low17 }其实c语言标准库已经提供了二分查找算法,调用标准库之前我们必须首先定义一个cmp 比较函数,作为函数指针传给bsearch 函数对于字符串的比较函数:1 int cmp(const void* a, const void* b)2 {3 assert(a != NULL && b != NULL);4 const char** lhs = (const char**)a;5 const char** rhs = (const char**)b;6 return strcmp(*lhs, *rhs);7 }字符串的比较函数为什么不是直接return strcmp((char*)a, (char*)b) ? 而是首先转为指针的指针,然后再引用元素?首先我们必须要知道比较函数cmp(void* a, void* b) 指针a和指针b是直接指向需要做比较的元素的,而在字符串比较函数中,因为char* a[] 是一个指针数组,即数组中每个元素都是一个指针,指向需要做比较的元素如果我们直接写成 return strcmp((char*)a, (char*)b) 则我们是在对数组中的元素做比较,而数组中的元素是一个内存地址(此时将一个内存地址解释为1个字节的char来做比较),实际上它所指向的元素才是我们需要比较的,所以这里有个二级指针9. 循环有序数组中查找== val 的元素,若找到则返回下标位置,若未找到则返回-1这里我们对循环有序数组做一下限制,原本数组应该是全部有序,如 a = {0, 1, 4, 5, 6, 10, 25, 28}这里我们从某一位置将数组切成两半,将后一半整体挪到数组前面去,例如 a = {5, 6, 10, 25, 28, 0, 1, 4}这样每次定位到一个mid时,会出现两种类型的子数组:(1) {5, 6, 10, 25} 全部有序的子数组:当子数组的第一个元素<= 最后一个元素时,我们可以肯定该子数组是有序的为什么呢?会不会出现{5, 6, 10, 0, 25} 或者{5, 6, 10, 25, 15}这样的呢?答案是不会,大家想想这两段数组是怎么来的就知道了(2) {28, 0, 1, 4} 不是全部有序的子数组当a[mid] == val 时直接return mid当a[low] <= a[mid] 且a[low] <= val < a[mid] 时, 此时搜索区间肯定转到mid 左边,反之就是右边当a[low] > a[mid] 且 a[mid] < val <= a[high]时,此时搜索区间肯定转到mid 右边,反之就是左边这里我们还必须认识到一点:任意查找时刻,只能处于以下3种情况:a. mid左边是全部有序mid右边也是全部有序b. mid左边非全部有序,mid 右边是全部有序c. mid左边全部有序,mid右边是非全部有序即任何时候,都至少有一个区间是全部有序的,我们就是对这个区间进行准确的判断查找值是否在该区间1 int binary_search(int* a, int len, int val)2 {3 assert(a != NULL && len > 0);4 int low = 0;5 int high = len - 1;6 while (low <= high) {7 int mid = low + (high - low) / 2;8 if (a[mid] == val) return mid;9 if (a[low] <= a[mid]) {10 if (a[low] <= val && val < a[mid])11 high = mid - 1;12 else13 low = mid + 1;14 } else {15 if (a[mid] < val && val <= a[high])16 high = mid + 1;17 else18 low = mid - 1;19 }20 }21 return -1;22 }。

相关文档
最新文档