折半查找法
- 格式:docx
- 大小:670.12 KB
- 文档页数:17
先看看这个,下面有例子折半查找:二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好;其缺点是要求待查表为有序表,且插入删除困难。
因此,折半查找方法适用于不经常变动而查找频繁的有序列表。
首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。
重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
算法要求算法复杂度下面提供一段二分查找实现的伪代码:BinarySearch(max,min,des)mid-<(max+min)/2while(min<=max)mid=(min+max)/2if mid=des thenreturn midelseif mid >des thenmax=mid-1elsemin=mid+1return max折半查找法也称为二分查找法,它充分利用了元素间的次序关系,采用分治策略,可在最坏的情况下用O(log n)完成搜索任务。
它的基本思想是,将n个元素分成个数大致相同的两半,取a[n/2]与欲查找的x作比较,如果x=a[n/2]则找到x,算法终止。
如果x<a[n/2],则我们只要在数组a的左半部继续搜索x(这里假设数组元素呈升序排列)。
如果x>a[n/2],则我们只要在数组a的右半部继续搜索x。
二分查找法一般都存在一个临界值的BUG,即查找不到最后一个或第一个值。
可以在比较到最后两个数时,再次判断到底是哪个值和查找的值相等。
C语言代码int BinSearch(SeqList * R,int n , KeyType K ){ //在有序表R[0..n-1]中进行二分查找,成功时返回结点的位置,失败时返回-1int low=0,high=n-1,mid;//置当前查找区间上、下界的初值if(R[low].key==K){return low ;}if(R[high].key==k)return high;while(low<=high){ //当前查找区间R[low..high]非空mid=low+((high-low)/2);//使用(low + high) / 2 会有整数溢出的问题(问题会出现在当low + high的结果大于表达式结果类型所能表示的最大值时,这样,产生溢出后再/2是不会产生正确结果的,而low+((high-low)/2)不存在这个问题if(R[mid].key==K){return mid;//查找成功返回}if(R[mid].key>K)high=mid-1; //继续在R[low..mid-1]中查找elselow=mid+1;//继续在R[mid+1..high]中查找}if(low>high)return -1;//当low>high时表示查找区间为空,查找失败} //BinSeareh折半查找程序举例程序要求:1.在main函数中定义一个20个元素的int数组,完成初始化和显示操作。
折半查找法c语言折半查找法,又称二分查找法,是一种在有序数据集(顺序表/列表、数组等)中,快速查找指定值的高效算法。
折半查找法的思想是基于二分法思想,用“分而治之”的思想来快速查找指定值。
折半查找法是一种最常用的查找方法,它也被称为是一种“有序”查找,因为要查找的数据必须是已经排好序的。
实际上,折半查找法的实现只要将有序的数据列折半,一次比较即可将待查找的值与被折半的数据列比较,这样查找的过程会比较快捷。
下面就来介绍折半查找法的具体实现方式:折半查找法假设要查找的数据是一个有序数列,在这里以升序数列为例:(1)先定义一个指向待查找序列低位的索引,称之为low;(2)定义另一个指向待查找序列高位的索引,称之为high;(3)首先用low与high计算中位索引 mid,将这个中位索引处的值与要查找的数据进行比较,如果相等,则搜索成功;(4)如果不等,则根据要查找的数据与中位索引处的值的比较结果,将待查找的序列分为两部分,下次查找只要在其中一部分序列中继续进行折半查找即可。
有了上面的思路,我们就可以用c语言来实现折半查找法了。
代码如下:#include<stdio.h>int binary_search(int arr[], int n, int key){int low, mid, high;low = 0;high = n-1;while(low <= high){mid = (low + high) / 2;if(arr[mid] == key)return mid;else if(arr[mid] > key)high = mid - 1;elselow = mid + 1;}return -1;}int main(){int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; int res = binary_search(arr, 10, 7);printf(res = %d res);return 0;}以上就是一个最基本的折半查找法的实现,通过定义一个low、high和mid三个索引,在计算中位索引mid时,low和high 分别指向有序数列的低位和高位,根据判断条件,如果要查找的值等于中位索引处的数据,则查找成功,否则就用待查找的数据与中位索引处的数据进行比较,来确定下一次查找的范围。
c语言折半查找法代码折半查找法,也称二分查找法,是一种高效的查找算法。
它的基本思想是将有序数组分成两部分,通过比较中间元素和目标元素的大小关系,来确定目标元素在哪一部分中,然后再在该部分中继续进行查找,直到找到目标元素或者确定目标元素不存在为止。
下面是C语言实现折半查找法的代码:```#include <stdio.h>int binarySearch(int arr[], int left, int right, int target) {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;}int main() {int arr[] = {1, 3, 5, 7, 9, 11, 13, 15};int n = sizeof(arr) / sizeof(arr[0]);int target = 7;int index = binarySearch(arr, 0, n - 1, target);if (index == -1) {printf("目标元素不存在\n");} else {printf("目标元素在数组中的下标为:%d\n", index);}return 0;}```在上面的代码中,binarySearch函数接收四个参数:数组arr、左边界left、右边界right和目标元素target。
它通过while循环不断缩小查找范围,直到找到目标元素或者确定目标元素不存在为止。
其中,mid表示当前查找范围的中间位置,通过比较arr[mid]和target的大小关系来确定目标元素在哪一部分中。
二分法的算法描述
二分法算法描述
二分法是一种常用的算法,也称为折半查找法。
它的基本思想是将一个有序的数组分成两个部分,然后判断目标值在哪个部分,再在该部分中继续进行查找,直到找到目标值或者确定目标值不存在为止。
二分法的算法描述如下:
1. 首先,确定数组的左右边界,即左边界为0,右边界为数组长度减1。
2. 然后,计算出数组的中间位置,即中间位置为左右边界之和除以2。
3. 接着,判断目标值与中间位置的值的大小关系,如果目标值小于中间位置的值,则在左半部分继续查找,否则在右半部分继续查找。
4. 如果目标值等于中间位置的值,则直接返回中间位置。
5. 如果左右边界相遇,但是目标值仍未找到,则说明目标值不存在,返回-1。
6. 如果目标值在左半部分,则将右边界设为中间位置减1,继续执行步骤2。
7. 如果目标值在右半部分,则将左边界设为中间位置加1,继续执行步骤2。
二分法的时间复杂度为O(log n),比线性查找的时间复杂度O(n)要快得多。
因此,在需要查找有序数组中的元素时,二分法是一种非常高效的算法。
二分法的应用场景很多,例如在搜索引擎中,可以使用二分法来查找关键词在文档中的位置;在游戏中,可以使用二分法来查找玩家的位置等等。
二分法是一种非常实用的算法,可以大大提高查找效率,值得我们在编程中多加应用。
Raptor是一个教育性的计算机编程学习工具,用于可视化算法和程序设计。
虽然Raptor 通常用于教学和理解算法的工作原理,但它并不是一个实际的编程语言或编译器,因此它不能直接执行代码。
然而,您可以使用Raptor来可视化算法的执行过程,包括折半查找法。
以下是使用Raptor可视化折半查找法的一般步骤:1. 打开Raptor:首先,打开Raptor编程学习工具。
2. 创建一个新程序:在Raptor中创建一个新的程序,以便开始构建折半查找算法。
3. 添加输入:在程序中添加输入,通常是一个有序的数组和要查找的目标元素。
您可以使用Raptor的输入操作符(通常是箭头符号)来模拟输入。
4. 初始化变量:创建变量来存储搜索范围的开始和结束索引以及中间索引。
初始化这些变量的值,通常开始索引为0,结束索引为数组的长度减1。
5. 创建循环结构:使用循环结构(通常是while循环)来执行折半查找。
循环条件通常是开始索引小于等于结束索引。
6. 计算中间索引:在每次迭代中,计算中间索引,通常通过将开始索引和结束索引相加并除以2来实现。
7. 比较中间元素:比较中间索引处的元素与目标元素。
如果它们相等,则找到了目标元素,结束搜索。
如果中间元素大于目标元素,则将结束索引更新为中间索引-1,否则将开始索引更新为中间索引+1。
8. 重复循环:根据比较的结果,重复步骤6和步骤7,直到找到目标元素或搜索范围缩小为0。
9. 输出结果:在找到目标元素或确定不存在时,输出搜索的结果。
10. 结束程序:完成折半查找的过程后,结束程序。
请注意,Raptor中的操作符和符号可能与实际编程语言有所不同,但上述步骤描述了折半查找算法的基本思想,您可以使用Raptor来可视化该算法的执行过程。
折半查找法的查找速度一定比顺序查找法快。
不能笼统的说那个算法一定就好,算法分析要看条件和模型。
折半算法要求待查区域数据是已经排好序的,但是顺序查找没这个要求。
算法时间分析要看平均情况、最坏情况、最好情况的。
最好情况两者
时间一样,因为都是比较方法查找,都假定第一次比较就找到。
最坏情况,折半查找更优为log n次比较,而顺序查找为n次比较。
平均情况下(所
有待查元素查找概率相当),一般是折半查找由于顺序查找(O(log n) < O(n))。
一般数据规模稍大的测试、算法练习题,折半查找表现都很好,常常
优于顺序查找,毕竟顺序查找算不上什么高等算法,优化空间很小。
但是,实际的查找操作很复杂,并不是查找数量多了就会趋近于平均
情况,而且折半查找又要求有排序,所以仍然需要按照系统需求进行相应
的数学分析和实际检测。
寻找最大最小值在数学和计算机领域中,寻找最大最小值是一项常见而重要的任务。
无论是在统计数据中找到最大值和最小值,还是在优化问题中寻找最大值和最小值,都需要采用适当的算法和方法。
本文将介绍一些常见的寻找最大最小值的算法和技巧,希望对读者有所启发。
一、暴力法最简单的寻找最大最小值的方式是使用暴力法。
该方法的原理是遍历整个数据集,分别找到最大值和最小值。
这种方法的时间复杂度为O(n),其中n是数据集的大小。
虽然暴力法非常直观和易实现,但对于大规模数据集来说效率较低。
二、折半查找法折半查找法也称为二分查找法,适用于有序数列。
它将数据集一分为二,通过比较目标值和中间值的大小关系,迭代地缩小查找范围,最终找到目标值。
对于有序数据集,折半查找法的时间复杂度为O(log n),其中n是数据集的大小。
相比暴力法,折半查找法的效率更高。
三、分治法分治法是一种将问题分解为子问题并分别解决的方法。
对于寻找最大最小值的问题,可以将数据集分成几个较小的子集,分别找到每个子集的最大最小值,然后将得到的结果进行比较,得出整个数据集的最大最小值。
分治法的关键是如何划分子问题和合并子问题的解。
该方法的时间复杂度取决于划分和合并的策略,通常为O(n log n)。
四、动态规划动态规划是一种通过利用子问题的解来求解原问题的方法。
对于寻找最大最小值的问题,可以使用动态规划来优化算法。
动态规划通常分为求解最优值和求解最优策略两个步骤。
在求解最大最小值的问题中,我们只需要关注最优值。
动态规划的时间复杂度通常为O(n^2),其中n是数据集的大小。
总结:寻找最大最小值是一项常见的任务,可以使用暴力法、折半查找法、分治法和动态规划等方法来解决。
不同的方法适用于不同的问题和数据集,选择合适的方法可以提高算法的效率。
在实际应用中,还可以根据具体问题的特点设计和优化算法,以满足实际需求。
通过不断学习和实践,我们可以掌握更多寻找最大最小值的技巧和方法,提高算法设计和问题解决的能力。
二分查找法,也称为折半查找法,是一种在有序数组中查找特定元素的算法。
它的要求如下:
1. 数组必须是有序的:二分查找法只能在有序数组中进行查找,如果数组无序,需要先进行排序。
2. 数组必须是静态的:二分查找法适用于静态数组,即不会频繁插入或删除元素的数组。
如果数组需要频繁修改,建议使用其他数据结构。
3. 数组元素必须可比较:二分查找法依赖于元素之间的比较操作,因此数组元素必须支持比较操作。
对于自定义类型的元素,需要实现比较操作符。
4. 查找范围必须确定:二分查找法需要明确查找范围的起始和结束位置,通常使用两个指针来表示。
5. 查找范围必须缩小:二分查找法通过不断缩小查找范围来逼近目标元素,直到找到目标元素或确定目标元素不存在。
总结起来,二分查找法的要求是有序数组、静态数组、可比较元素、确定查找范围和缩小查找范围。
二分法查找算法二分法查找算法,又称折半查找,是一种基于有序数组的查找算法。
它采用了逐步缩小查找范围的方法,能高效地找出目标数字在数组中的位置。
下面我们就来具体了解一下二分法查找算法的步骤。
第一步,确定查找范围。
由于二分法查找算法只适用于有序数组,所以我们需要先对数组进行排序。
然后,我们需要确定查找的范围,也就是最大值和最小值。
一般来说,最大值为数组末尾的值,最小值为数组开头的值。
第二步,找到中间值。
我们需要计算出最大值和最小值的平均值,来确定中间值。
由于数组是有序的,所以我们可以使用简单的方法计算中间值:中间值 = (最大值 + 最小值)/ 2。
如果中间值与目标数字相等,那么我们就找到了目标数字的位置;如果中间值比目标数字大,那么目标数字应该在左边,我们将右边的范围缩小到中间值左边的数字;如果中间值比目标数字小,目标数字应该在右边,我们将左边的范围缩小到中间值右边的数字。
第三步,重复查找过程。
我们继续按照上面的方法缩小查找范围,并不断计算中间值,直到找到目标数字的位置或者确定目标数字不存在于数组中为止。
如果查找范围被缩小到了最小值等于最大值的时候,且这个值不等于目标数字,说明目标数字不存在于数组中。
二分法查找算法的时间复杂度为O(log n),是一种快速的查找算法。
但是它也有一些局限性,只适用于有序数组,不适用于链表等其他数据结构。
在有序数组中,如果需要频繁进行插入和删除操作,排序的时间复杂度会很高,影响算法效率。
以上就是二分法查找算法的基本步骤及其局限性。
在实际开发中,我们需要根据具体情况来选择使用哪种查找算法,在考虑算法效率的同时,也要考虑其他因素,比如数据结构的特点、操作的频率等等,才能选出最适合的算法。
折半查找算法思想:将数列按有序化(递增或递减)排列,查找过程中采用跳跃式方式查找,即先以有序数列的中点位置为比较对象,如果要找的元素值小于该中点元素,则将待查序列缩小为左半部分,否则为右半部分。
通过一次比较,将查找区间缩小一半。
折半查找是一种高效的查找方法。
它可以明显减少比较次数,提高查找效率。
但是,折半查找的先决条件是查找表中的数据元素必须有序。
算法步骤描述:step1 首先确定整个查找区间的中间位置mid = (left + right )/ 2step2 用待查关键字值与中间位置的关键字值进行比较;若相等,则查找成功若大于,则在后(右)半个区域继续进行折半查找若小于,则在前(左)半个区域继续进行折半查找Step3 对确定的缩小区域再按折半公式,重复上述步骤。
最后,得到结果:要么查找成功,要么查找失败。
折半查找的存储结构采用一维数组存放。
折半查找算法举例对给定数列(有序){ 3,5,11,17,21,23,28,30,32,50},按折半查找算法,查找关键字值为30的数据元素。
折半查找的算法讨论:优点: ASL≤log2n,即每经过一次比较,查找范围就缩小一半。
经log2n 次计较就可以完成查找过程。
缺点:因要求有序,所以要求查找数列必须有序,而对所有数据元素按大小排序是非常费时的操作。
另外,顺序存储结构的插入、删除操作不便利。
#include <iostream>using namespace std;int Find_Half_Line(int low,int high,int Find_Name,int a[])...{while(low <= high)...{int mid = (low + high)/2;if(a[mid] == Find_Name) //如果相等则返回return mid;elseif(Find_Name > a[mid]) //大于查找值最低的值变为折半中间的值low =mid+1;else high=mid-1; //小于最大值变为中间值}return -1;}int main()...{int Find_Name;int low=0,high=9;int a[10]=...{2,3,5,8,10,12,15,17,19,20};cin >> Find_Name;cout <<Find_Half_Line(low,high,Find_Name,a);return 0;}插入排序插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子文件中的适当位置,直到全部记录插入完成为止。
c语言使用折半查找法的示例代码C语言使用折半查找法的示例代码1. 引言折半查找法(Binary Search)是一种常用的查找算法,它通过将有序数组分成两半的方式快速定位要查找的元素。
在本文中,我们将探讨C语言中如何实现折半查找的算法,并提供一个示例代码来演示其实际应用。
2. 算法思路折半查找法的基本思路是不断将查找范围缩小为一半,直到找到目标元素或者确认目标元素不存在。
以下是该算法的详细步骤:- 确定查找范围的起始位置(通常是数组的起始位置)和结束位置(通常是数组的末尾位置)。
- 计算查找范围的中间位置,并取得该位置上的元素。
- 如果中间元素等于目标元素,则查找成功,并返回该元素的位置。
- 如果中间元素大于目标元素,则将查找范围缩小为数组起始位置到中间位置-1的一半。
- 如果中间元素小于目标元素,则将查找范围缩小为中间位置+1到数组末尾位置的一半。
- 重复以上步骤,直到找到目标元素或者确认目标元素不存在。
3. 示例代码下面是一个使用C语言实现折半查找法的示例代码:```c#include <stdio.h>int binarySearch(int arr[], int low, int high, int target) { while (low <= high) {int mid = low + (high - low) / 2;if (arr[mid] == target) {return mid;}else if (arr[mid] < target) {low = mid + 1;}else {high = mid - 1;}}return -1; // 目标元素不存在的情况int main() {int arr[] = {1, 3, 5, 7, 9, 11, 13};int size = sizeof(arr) / sizeof(arr[0]);int target = 9;int result = binarySearch(arr, 0, size - 1, target);if (result == -1) {printf("目标元素不存在\n");}else {printf("目标元素在数组中的位置为:%d\n", result);}return 0;}```4. 代码解析上述示例代码中,我们首先定义了一个名为`binarySearch`的函数,该函数接受一个有序数组`arr`、查找范围的起始位置`low`、结束位置`high`和目标元素`target`作为参数。
折半查找法算法
折半查找法是一种在有序数组中查找某一特定元素的搜索算法。
它的基本思想是:首先,将数组的中间位置的元素与要查找的元素进行比较,如果相等,则查找成功;如果比要查找的元素大,则在数组的前半部分继续查找;如果比要查找的元素小,则在数组的后半部分继续查找。
这种方法可以大大减少查找的次数,提高查找的效率。
折半查找法的步骤如下:
1. 首先,从有序数组的中间位置开始查找,将中间位置处的元素与要查找的元素进行比较。
2. 如果相等,则查找成功;
3. 如果比要查找的元素大,则在数组的前半部分继续查找;
4. 如果比要查找的元素小,则在数组的后半部分继续查找;
5. 重复上述步骤,直到找到要查找的元素,或者查找范围为空。
折半查找法的时间复杂度为O(log2n),其中n为数组的长度。
它的优点是查找速度快,比
顺序查找要快得多,而且它只需要对数组进行一次排序,就可以多次使用。
但是,它的缺点是只能用于有序数组,如果数组无序,则必须先进行排序,才能使用折半查找法。
总之,折半查找法是一种高效的查找算法,它可以大大减少查找的次数,提高查找的效率。
但是,它只能用于有序数组,如果数组无序,则必须先进行排序,才能使用折半查找法。
折半查找的递归算法1. 介绍折半查找,也称为二分查找,是一种在有序数组中查找目标值的常用算法。
它的时间复杂度为O(logN),相比于线性查找的O(N)效率更高。
折半查找的核心思想是每次将查找范围缩小一半,直到找到目标值或者确认目标值不存在。
2. 算法原理折半查找算法的原理非常简单,基本思路如下: 1. 确定查找范围的起始位置(一般为数组的首尾元素)。
2. 计算范围的中间位置。
3. 判断中间位置的元素与目标值的关系: - 如果中间元素等于目标值,查找成功。
- 如果中间元素大于目标值,缩小查找范围至左侧一半,回到第2步。
- 如果中间元素小于目标值,缩小查找范围至右侧一半,回到第2步。
4. 重复步骤2和3,直到找到目标值或者确认目标值不存在。
3. 递归实现折半查找可以使用递归的方式实现,递归版本的算法如下:def binary_search_recursive(arr, target, left, right):if left > right:return -1mid = (left + right) // 2if arr[mid] == target:return midif arr[mid] > target:return binary_search_recursive(arr, target, left, mid - 1) else:return binary_search_recursive(arr, target, mid + 1, right)在递归版本的算法中,参数arr是要进行查找的有序数组,target是目标值,left和right分别表示当前查找范围的左右边界。
算法的停止条件是左边界大于右边界,表示无法再缩小查找范围。
4. 算法分析接下来我们来分析折半查找的递归算法的时间复杂度和空间复杂度。
时间复杂度每次递归时,查找范围缩小一半,因此递归的层数最多为log2(N)。
数据结构50:⼆分查找法(折半查找法)折半查找,也称⼆分查找,在某些情况下相⽐于顺序查找,使⽤折半查找算法的效率更⾼。
但是该算法的使⽤的前提是静态查找表中的数据必须是有序的。
例如,在{5,21,13,19,37,75,56,64,88 ,80,92}这个查找表使⽤折半查找算法查找数据之前,需要⾸先对该表中的数据按照所查的关键字进⾏排序:{5,13,19,21,37,56,64,75,80,88,92}。
在折半查找之前对查找表按照所查的关键字进⾏排序的意思是:若查找表中存储的数据元素含有多个关键字时,使⽤哪种关键字做折半查找,就需要提前以该关键字对所有数据进⾏排序。
折半查找算法对静态查找表{5,13,19,21,37,56,64,75,80,88,92}采⽤折半查找算法查找关键字为 21 的过程为:图 1 折半查找的过程(a)如上图 1 所⽰,指针 low 和 high 分别指向查找表的第⼀个关键字和最后⼀个关键字,指针 mid 指向处于 low 和 high 指针中间位置的关键字。
在查找的过程中每次都同 mid 指向的关键字进⾏⽐较,由于整个表中的数据是有序的,因此在⽐较之后就可以知道要查找的关键字的⼤致位置。
例如在查找关键字 21 时,⾸先同 56 作⽐较,由于21 < 56,⽽且这个查找表是按照升序进⾏排序的,所以可以判定如果静态查找表中有 21这个关键字,就⼀定存在于 low 和 mid 指向的区域中间。
因此,再次遍历时需要更新 high 指针和 mid 指针的位置,令 high 指针移动到 mid 指针的左侧⼀个位置上,同时令 mid 重新指向 low 指针和 high 指针的中间位置。
如图 2 所⽰:图 2 折半查找的过程(b)同样,⽤ 21 同 mid 指针指向的 19 作⽐较,19 < 21,所以可以判定 21 如果存在,肯定处于 mid 和 high 指向的区域中。
所以令 low 指向 mid 右侧⼀个位置上,同时更新 mid 的位置。
折半查找描述的算法
折半查找(Binary Search)是一种查找算法,适用于已排序数组或列表。
其算法步骤如下:
1. 初始化一个左指针left和一个右指针right。
left指向数组的起始位置,right 指向数组的末尾位置。
2. 计算中间位置mid = (left+right) / 2。
如果数组的大小为奇数,则mid是中间元素的索引;如果数组的大小为偶数,则mid是中间两个元素中的较小索引。
3. 比较中间元素[mid]和目标值target的大小。
- 如果[mid] == target,则找到目标值,返回mid。
- 如果[mid] < target,则目标值可能在[mid+1, right]之间,更新left = mid + 1,重复步骤2。
- 如果[mid] > target,则目标值可能在[left, mid-1]之间,更新right = mid - 1,重复步骤2。
4. 重复步骤2和步骤3,直到left > right或者找到目标值。
如果找到目标值,则返回其索引;如果找不到目标值,则返回-1。
折半查找的时间复杂度为O(log n),其中n是数组的大小。
由于每次都将搜索区间缩小一半,因此它是一种高效的查找算法。
折半查找原理
嘿,朋友们!今天咱来聊聊折半查找原理呀!这玩意儿就像是在一个大宝藏里找宝贝。
你想啊,假如你有一堆乱七八糟的东西,要找其中一个特定的玩意儿,你会咋办?总不能一个一个瞎翻吧,那得找到啥时候呀!折半查找就聪明多啦。
它就像是你有一把神奇的尺子,一下子把这堆东西分成两半。
然后呢,你看看你要找的宝贝在左边那堆还是右边那堆。
如果在左边,那好呀,右边那堆就可以先不管啦,就专门对付左边这堆。
然后再把左边这堆又分成两半,继续这么找下去。
这多有意思呀!就好像你在走迷宫,每次都能找到最有可能的那条路。
你说,这是不是比瞎转悠强多啦?
咱再打个比方,你去图书馆找一本书。
要是没有折半查找,那你不得在那一排排书架上挨个找呀,那得累个半死。
可要是用了折半查找呢,就像你知道了一个小窍门,一下子就能缩小范围,快速找到那本书的大概位置。
折半查找不就是这样嘛,它能让你快速地在一堆数据里找到你想要的那个。
而且呀,它还特别靠谱,只要数据是有序的,它就像个小侦探一样,准能把目标给揪出来。
你说这折半查找是不是很神奇?它就像一把钥匙,能打开那扇通往目标的门。
你想想看,要是没有它,我们得费多大的劲呀!
在生活中,我们不也经常需要这样快速找到目标的方法吗?比如说找东西呀,找信息呀。
折半查找原理就像是我们的好帮手,让我们的寻找变得更加高效。
所以呀,大家可别小瞧了这个折半查找原理,它可是有着大用处呢!学会了它,就好像你多了一项超能力,能在数据的海洋里畅游无阻,快速找到你想要的宝贝!难道不是吗?。
二分查找是在我们整个数据结构当中一个比较重要的算法,它的思想在我们的实际开发过程当中应用得非常广泛。
在实际应用中,有些数据序列是已经经过排序的,或者可以将数据进行排序,排序后的数据我们可以通过某种高效的查找方式来进行查找,今天要讲的就是折半查找法(二分查找),它的时间复杂度为O(logn),将以下几个方面进行概述
了解二分查找的原理与思想
分析二分查找的时间复杂度
掌握二分查找的实现方法
了解二分查找的使用条件和场景
1 二分查找的原理与思想
在上一个章节当中,我们学习了各种各样的排序的算法,接下来我们就讲解一下针对有序集合的查找的算法—二分查找(Binary Search、折半查找)算法,二分查找呢,是一种非常容易懂的查找算法,它的思想在我们的生活中随处可见,比如说:同学聚会的时候喜欢玩一个游戏——猜数字游戏,比如在1-100以内的数字,让别人来猜从,猜的过程当中会被提示是猜大了还是猜小了,直到猜中为止。
这个过程其实就是二分查找的思想的体现,这是个生活中的例子,在我们
现实开发过程当中也有很多应用到二分查找思想的场景。
比如说仙现在有10个订单,它的金额分别是6、12 、15、19、24、26、29、35、46、67 请从中找出订单金额为15的订单,利用二分查找的思想,那我们每一次都会与中间的数据进行比较来缩小我们查找的范围,下面这幅图代表了查找的过程,其中low,high代表了待查找的区间的下标范围,mid表示待查找区间中间元素的下标(如果范围区间是偶数个导致中间的数有两个就选择较小的那个)
第一次二分查找
第二次二分查找
第三次二分查找
通过这个查找过程我们可以对二分查找的思想做一个汇总:二分查找针对的是一个有序的数据集合,查找思想有点类似于分治思想。
每次都通过跟区间的中间元素对比,将待查找的区间范围缩小为原来的一半,直到找到要查找的元素,或者区间被缩小为0。
一:查找的数据有序
二:每次查找,数据的范围都在缩小,直到找到或找不到为止。
2 二分查找的时间复杂度
我们假设数据大小为n,每次查询完之后,数据就缩减为原来的一半,直到最后的数据大小被缩减为1
n,n/2,n/4,n/8,n/16,n/32,…………,1
这是一个等比数列,当数据大小变为1时,
k是总共缩小的次数,而每次缩小只涉及两个数据的比较大小,所以经过了K次区间缩小操作,通过计算k的值我们就可以得出二分查找的时间复杂度是O(logn)
这是一种非常高效的时间复杂度,有时候甚至比O(1)复杂度更高效,为什么这么说呢?因为对于logn来说即使n的非常大,对应的logn的值也会很小,之前在学习O(1)时间复杂度时我们说过O(1)代表的是一种常量级的时间复杂度,并不是说代码只需要执行一条语句,有时候可能要执行100次,1000次,这样常规级次数都用O(1)来表示,所以,常量级时间复杂度的算法有时候还没有O(logn)的算法执行效率高。
3 二分查找算法的实现
I 有序数列当中不存在重复的元素
*/
//递归二分查找//
int binaS(int*arr,int key,int high,int low) {
if(low>high)
return -1;
int mid=(high+low)/2;
if(arr[mid]==key)
{
return mid;
}
else if(arr[mid]>key)
{
binaS(arr,key,low,mid-1);
}
else
{
binaS(arr,key,mid+1,high);
}
}
int main()
{
//二分查找
int a[4]={11,22,33,44};
int key;
cin>>key;
cout<<binaS(a,key,0,3);
// int low=0,high=3,flag=1,mid;
// while(low<=high)
// {
// mid=(low+high)/2;
// if(key==a[mid])
// {
// cout<<mid<<" ";
//
// //flag=0;
// //break;
// }
// else if(key<a[mid])
// {
// high=mid-1;
II 有序数列当中存在重复的元素思路1:
//当我们的mid指针已经指向第一个元素或者我们的mid指针前一个元素不等于我们的查找
//元素的时候,直接返回mid下标
if(mid==0 || array[mid-1]!=value)
{
return mid;
} //否则,继续二分查找
else
{
high=mid-1;
}
}
else if(array[mid]<value)
{
low=mid+1;
}
else if(array[mid]>value)
{
high=mid-1;
}
}
思路2:
while(low<=high)
{
int mid=low+(high-low)/2;
if(arr[mid]==value)
{
//和查找第一个元素的思路是一样的
if(mid==len-1 || arr[mid+1]!=value) return mid;
//否则继续查找,往后查找
else
{
low=mid+1;
}
}
else if(arr[mid]>value)
{
high=mid-1;
}
else if(arr[mid]<value)
{
low=mid+1;
}
if(arr[mid]>=value)
{
if(mid==0||arr[mid-1]<value) 一定要小于value 1 3 5 7 9 如果是2,那不行
return mid;
else
high=mid-1;
}
else if(arr[mid]<value)
{
low=mid+1;
}
}
return -1;
*/
int binarySearch(int*arr,int value,int len)
{
int low=0,high=len-1,max=-1;
while(low<=high)
{
int mid=low+(high-low)/2;
if(arr[mid]==value)
{
if(mid==0||arr[mid-1]!=value)
{
return mid;
}
else
{
high=mid-1;
}
}
else if(arr[mid]>value)
{
max=mid;
high=mid-1;
}
else if(arr[mid]<value)
{
low=mid+1;
}
}
int low=0,higg=len-1;
while(low<=high)
{
int mid=low+(high-low)>>1;
if(arr[mid]<=value) //11 22
{
if(mid==len-1||arr[mid+1]>value)
return mid;
else
low=mid+1;
}
else
{
high=mid-1;
}
}
return -1;
}
int main()
{
二分查找法的使用条件和场景
拓展:log2N → O(logN) → loga N=logcN/logca,因1/logca 不是1,所以舍去,剩下logcN,c可以是任何的值,不关心,所以是logN
案例一:跳房子(这…,看题我都要看半小时)。