二分搜索及其扩展(循环递增数组的搜索)

合集下载

二分查找法的算法过程

二分查找法的算法过程

二分查找法的算法过程
二分查找法(Binary Search)是一种在有序数组中查找特定元素的算法。

它的算法思想是将数组分为两部分,然后判断目标元素与中间元素的大小关系,进而确定目标元素在哪一部分中,然后再在相应的部分中继续进行查找,直到找到目标元素或确定目标元素不存在。

具体的算法过程如下:
1. 首先,确定数组的起始位置(start)和结束位置(end)。

- start 初始化为数组的第一个元素的索引。

- end 初始化为数组的最后一个元素的索引。

2. 然后,计算出数组的中间位置(mid)。

- mid = (start + end) / 2。

3. 接下来,比较目标元素与中间元素的大小关系。

- 如果目标元素等于中间元素,那么返回中间元素的索引,表示找到了目标元素。

- 如果目标元素小于中间元素,说明目标元素在数组的前半部分,所以将结束位置 end 更新为 mid - 1。

- 如果目标元素大于中间元素,说明目标元素在数组的后半部分,所以将起始位置 start 更新为 mid + 1。

4. 然后,再次计算新的中间位置,并重复步骤 3,直到找到目标元素或确定目标元素不存在。

- 如果 start 大于 end,表示数组中不存在目标元素。

通过以上的算法过程,可以高效地在有序数组中查找目标元素。

二分查找法的时间复杂度为 O(log n),其中 n 表示数组的长度。

它比线性查找等其他查找算法要更加高效,尤其适用于大规模数据的查找操作。

二分搜索算法实验报告

二分搜索算法实验报告

二分搜索算法实验报告篇一:实验报告2--二分搜索技术注意:红色的部分需要用自己的代码或内容进行替换。

湖南涉外经济学院实验报告实验课程:算法设计与分析实验项目:二分搜索技术学院专业实验地点分组组号实验时间 XX年 3 月 10 日星期一第 12节指导老师【实验目的和要求】1. 理解分治法的原理和设计思想;2.要求实现二分搜索算法;3.要求交互输入一组关键字序列,输入需要查找的关键字;4. 要求显示结果。

【系统环境】操作系统:Windows XP 操作系统开发工具:VC++6.0英文企业版开发语言:C,C++【实验原理】1、问题描述给定已排好序的n个元素a[0…n-1],现要在这n个元素中找出一特定元素x。

2、实验原理二分搜索方法充分利用了元素间的次序关系(但也局限于此),采用分治策略,将n个元素分成个数大致相同的两半,取a[n/2]与x进行比较。

如果x=a[n/2],则找到x,算法终止。

如果xa[n/2],则只要在数组a的右半部继续搜索x。

【实验任务与步骤】1、实验步骤(可以根据自己的程序修改)(1) 实现顺序搜索。

(2) 实现二分搜索算法的递归算法。

(3) 实现二分搜索算法的非递归算法。

(4) 编写主函数,调用所写的三个算法进行测试,并进行输出。

2、源程序代码// 此处为解决问题的完整源程序,要求带注释,代码必须符合书写规范。

(1) 顺序搜索(2) 递归的二分搜索(3) 非递归的二分搜索(原文来自:小草范文网:二分搜索算法实验报告)……【实验结论(包括实验数据处理、问题与解决办法、心得体会、意见与建议等)】// 此处为程序运行的结果,要求有程序运行输入输出实例,要求至少有两组实验结果。

// 必须写心得体会、意见与建议等,或者遇到的问题、难题等。

……篇二:查找排序实验报告实验十:查找、排序计算机学院 12级2班 12110XX 李龙实验目的:1.掌握折半查找算法的思想。

2.实现折半查找的算法。

3.掌握常见的排序算法(插入排序、交换排序、选择排序等)的思想、特点及其适用条件。

实验一 二分搜索算法

实验一  二分搜索算法

实验一二分搜索算法E08620311-方凯-08计算机(3)班一.实验目的:1、理解分治算法的概念和基本要素;2、理解递归的概念;3、掌握设计有效算法的分治策略;4、通过二分搜索技术学习分治策略设计技巧;二.实验内容及要求:1.使用二分搜索算法查找任意N个有序数列中的指定元素。

2.通过上机实验进行算法实现。

3.保存和打印出程序的运行结果,并结合程序进行分析,上交实验报告。

4.至少使用两种方法进行编程。

二.实验原理:二分搜索算法也称为折半查找法,它充分利用了元素间的次序关系,采用分治策略,可在最坏的情况下用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。

二分搜索法的应用极其广泛,而且它的思想易于理解。

第一个二分搜索算法早在1946年就出现了,但是第一个完全正确的二分搜索算法直到1962年才出现。

Bentley在他的著作《Writing Correct Programs》中写道,90%的计算机专家不能在2小时内写出完全正确的二分搜索算法。

问题的关键在于准确地制定各次查找范围的边界以及终止条件的确定,正确地归纳奇偶数的各种情况,其实整理后可以发现它的具体算法是很直观的。

方法一:直接查找;方法二:递归查找;方法三:迭代查找;四.程序代码:方法1:直接查找int BinarySearch(int a[],int x,int n){int left=0;int right=n-1;while(left<=right){int middle=(left+right)/2;if(x==a[middle])return middle;if(x>a[middle])left=middle+1;else right=middle-1;}return-1;}方法2:递归查找int BinarySearchDG(int a[],int x,int left,int right){int middle=(left+right)/2;if(left<=right){if(x==a[middle])return middle;if(x>a[middle])return BinarySearchDG(a,x,middle+1,right);else return BinarySearchDG(a,x,left,middle-1);}return-1;}五.结果运行与分析:for(int i=0;i<100;i++){a[i]=2*i-1;}我的数组是1,3,5,7,9……195,197所以57在数组的位置是29位,都没错。

binarysearch使用方法

binarysearch使用方法

binarysearch使用方法Binary search是一种常见的查找算法,它能够在有序的数据集合中快速定位目标元素的位置。

本文将一步一步地介绍binary search的使用方法,帮助读者理解和掌握该算法。

第一步:了解binary search的原理首先,我们需要了解binary search的原理。

Binary search的基本思想是将有序集合分成两部分,然后判断目标元素位于哪个子集合中,再递归地在子集合中继续进行查找,直到找到目标元素或者确定目标元素不存在。

具体地说,如果要在一个已经按升序排列的数组中查找目标元素,那么可以选择数组的中间元素进行比较。

如果目标元素等于中间元素,则直接返回中间元素的位置;如果目标元素小于中间元素,则继续在前半部分子数组中查找;如果目标元素大于中间元素,则继续在后半部分子数组中查找。

通过每次将数组分成两部分,并根据目标元素与中间元素的比较结果确定下一步的查找方向,就可以快速定位目标元素。

第二步:实现binary search算法了解binary search的原理之后,我们需要实现该算法。

下面是一个基于递归的二分查找算法的示例代码(使用Python语言):def binary_search(arr, target):low = 0high = len(arr) - 1while low <= high:mid = (low + high) 2if arr[mid] == target:return midelif arr[mid] < target:low = mid + 1else:high = mid - 1return -1这段代码中,`binary_search`函数接受两个参数:一个有序的数组`arr`和目标元素`target`。

函数中的`low`和`high`分别表示当前子数组的起始和结束位置。

算法使用一个`while`循环来不断调整子数组的范围,直到找到目标元素或确定目标元素不存在。

二进制搜索算法简介

二进制搜索算法简介

二进制搜索算法简介二进制搜索算法(Binary Search Algorithm)是一种高效的搜索算法,用于在有序数组中查找特定元素的位置。

它的原理基于不断缩小搜索范围的思想,通过比较目标值与数组中间元素的大小关系,确定下一步搜索的方向。

1. 算法原理二进制搜索算法的核心思想是将搜索范围不断缩小至只包含目标元素的区间。

首先,确定数组的中间元素,将其与目标值进行比较。

若中间元素等于目标值,则直接返回其位置;若中间元素大于目标值,则在数组的左半部分继续搜索;若中间元素小于目标值,则在数组的右半部分继续搜索。

通过不断缩小搜索范围,最终可以找到目标元素或确定其不存在于数组中。

2. 算法步骤二进制搜索算法的具体步骤如下:(1)初始化搜索范围为整个数组,即左边界为0,右边界为数组长度减1。

(2)计算中间元素的位置,即左边界与右边界的平均值。

(3)比较中间元素与目标值的大小关系。

(4)若中间元素等于目标值,则返回其位置。

(5)若中间元素大于目标值,则将右边界缩小为中间元素的前一个位置,继续搜索左半部分。

(6)若中间元素小于目标值,则将左边界增大为中间元素的后一个位置,继续搜索右半部分。

(7)重复步骤(2)至(6),直到找到目标元素或搜索范围为空。

3. 算法优势二进制搜索算法相较于顺序搜索算法具有明显的优势。

首先,它可以在有序数组中快速定位目标元素的位置,时间复杂度为O(log n)。

相比之下,顺序搜索算法的时间复杂度为O(n),即需要遍历整个数组才能找到目标元素。

其次,二进制搜索算法的搜索范围不断缩小,避免了不必要的比较操作,提高了搜索效率。

因此,在大规模数据的搜索任务中,二进制搜索算法具有明显的优势。

4. 算法应用二进制搜索算法在实际应用中有广泛的应用。

例如,在搜索引擎中,对于关键词的搜索结果排序通常采用二进制搜索算法,以提高检索效率。

此外,在数据库索引、游戏开发等领域,二进制搜索算法也得到了广泛应用。

5. 算法限制尽管二进制搜索算法具有高效的特点,但它也有一定的限制。

ACM必须掌握的算法

ACM必须掌握的算法

ACM必须的算法1.最短路(Floyd、Dijstra,BellmanFord)2.最小生成树(先写个prim,kruscal要用并查集,不好写)3.大数(高精度)加减乘除4.二分查找. (代码可在五行以内)5.叉乘、判线段相交、然后写个凸包.6.BFS、DFS,同时熟练hash表(要熟,要灵活,代码要简)7.数学上的有:辗转相除(两行内),线段交点、多角形面积公式.8. 调用系统的qsort, 技巧很多,慢慢掌握.9. 任意进制间的转换第二阶段:练习复杂一点,但也较常用的算法。

:1. 二分图匹配(匈牙利),最小路径覆盖2. 网络流,最小费用流。

3. 线段树.4. 并查集。

5. 熟悉动态规划的各个典型:LCS、最长递增子串、三角剖分、记忆化dp6.博弈类算法。

博弈树,二进制法等。

7.最大团,最大独立集。

8.判断点在多边形内。

9. 差分约束系统. 10. 双向广度搜索、A*算法,最小耗散优先.相关的知识图论:路径问题 0/1边权最短路径 BFS 非负边权最短路径(Dijkstra)可以用Dijkstra解决问题的特征负边权最短路径Bellman-Ford Bellman-Ford的Yen-氏优化差分约束系统 Floyd 广义路径问题传递闭包极小极大距离 / 极大极小距离 EulerPath / Tour 圈套圈算法混合图的 Euler Path / TourHamilton Path / Tour 特殊图的Hamilton Path / Tour 构造生成树问题最小生成树第k小生成树最优比率生成树 0/1分数规划度限制生成树连通性问题强大的DFS算法无向图连通性割点割边二连通分支有向图连通性强连通分支 2-SAT最小点基有向无环图拓扑排序有向无环图与动态规划的关系二分图匹配问题一般图问题与二分图问题的转换思路最大匹配有向图的最小路径覆盖0 / 1矩阵的最小覆盖完备匹配最优匹配稳定婚姻网络流问题网络流模型的简单特征和与线性规划的关系最大流最小割定理最大流问题有上下界的最大流问题循环流最小费用最大流 / 最大费用最大流弦图的性质和判定组合数学解决组合数学问题时常用的思想逼近递推 / 动态规划概率问题Polya定理计算几何 / 解析几何计算几何的核心:叉积 / 面积解析几何的主力:复数基本形点直线,线段多边形凸多边形 / 凸包凸包算法的引进,卷包裹法Graham扫描法水平序的引进,共线凸包的补丁完美凸包算法相关判定两直线相交两线段相交点在任意多边形内的判定点在凸多边形内的判定经典问题最小外接圆近似O(n)的最小外接圆算法点集直径旋转卡壳,对踵点多边形的三角剖分数学 / 数论最大公约数Euclid算法扩展的Euclid算法同余方程 / 二元一次不定方程同余方程组线性方程组高斯消元法解mod 2域上的线性方程组整系数方程组的精确解法矩阵行列式的计算利用矩阵乘法快速计算递推关系分数分数树连分数逼近数论计算求N的约数个数求phi(N)求约数和快速数论变换……素数问题概率判素算法概率因子分解数据结构组织结构二叉堆左偏树二项树胜者树跳跃表样式图标斜堆reap统计结构树状数组虚二叉树线段树矩形面积并圆形面积并关系结构Hash表并查集路径压缩思想的应用 STL中的数据结构vectordequeset / map动态规划 / 记忆化搜索动态规划和记忆化搜索在思考方式上的区别最长子序列系列问题最长不下降子序列最长公共子序列最长公共不下降子序列一类NP问题的动态规划解法树型动态规划背包问题动态规划的优化四边形不等式函数的凸凹性状态设计规划方向线性规划常用思想二分最小表示法串KMPTrie结构后缀树/后缀数组 LCA/RMQ有限状态自动机理论排序选择/冒泡快速排序堆排序归并排序基数排序拓扑排序排序网络中级:一.基本算法:(1)C++的标准模版库的应用. (poj3096,poj3007)(2)较为复杂的模拟题的训练(poj3393,poj1472,poj3371,poj1027,poj2706)二.图算法:(1)差分约束系统的建立和求解. (poj1201,poj2983)(2)最小费用最大流(poj2516,poj2516,poj2195)(3)双连通分量(poj2942)(4)强连通分支及其缩点.(poj2186)(5)图的割边和割点(poj3352)(6)最小割模型、网络流规约(poj3308, )三.数据结构.(1)线段树. (poj2528,poj2828,poj2777,poj2886,poj2750)(2)静态二叉检索树. (poj2482,poj2352)(3)树状树组(poj1195,poj3321)(4)RMQ. (poj3264,poj3368)(5)并查集的高级应用. (poj1703,2492)(6)KMP算法. (poj1961,poj2406)四.搜索(1)最优化剪枝和可行性剪枝(2)搜索的技巧和优化 (poj3411,poj1724)(3)记忆化搜索(poj3373,poj1691)五.动态规划(1)较为复杂的动态规划(如动态规划解特别的施行商问题等)(poj1191,poj1054,poj3280,poj2029,poj2948,poj1925,poj3034)(2)记录状态的动态规划. (POJ3254,poj2411,poj1185)(3)树型动态规划(poj2057,poj1947,poj2486,poj3140)六.数学(1)组合数学:1.容斥原理.2.抽屉原理.3.置换群与Polya定理(poj1286,poj2409,poj3270,poj1026).4.递推关系和母函数.(2)数学.1.高斯消元法(poj2947,poj1487,poj2065,poj1166,poj1222)2.概率问题. (poj3071,poj3440)3.GCD、扩展的欧几里德(中国剩余定理) (poj3101)(3)计算方法.1.0/1分数规划. (poj2976)2.三分法求解单峰(单谷)的极值.3.矩阵法(poj3150,poj3422,poj3070)4.迭代逼近(poj3301)(4)随机化算法(poj3318,poj2454)(5)杂题.(poj1870,poj3296,poj3286,poj1095)七.计算几何学.(1)坐标离散化.(2)扫描线算法(例如求矩形的面积和周长并,常和线段树或堆一起使用).(poj1765,poj1177,poj1151,poj3277,po j2280,poj3004)(3)多边形的内核(半平面交)(poj3130,poj3335)(4)几何工具的综合应用.(poj1819,poj1066,poj2043,poj3227,poj2165,poj3429)高级:一.基本算法要求:(1)代码快速写成,精简但不失风格(poj2525,poj1684,poj1421,poj1048,poj2050,poj3306)(2)保证正确性和高效性. poj3434二.图算法:(1)度限制最小生成树和第K最短路. (poj1639)(2)最短路,最小生成树,二分图,最大流问题的相关理论(主要是模型建立和求解)(poj3155,poj2112,poj1966,poj3281,poj1087,poj2289,poj3216,poj2446(3)最优比率生成树. (poj2728)(4)最小树形图(poj3164)(5)次小生成树.(6)无向图、有向图的最小环三.数据结构.(1)trie图的建立和应用. (poj2778)(2)LCA和RMQ问题(LCA(最近公共祖先问题) 有离线算法(并查集+dfs) 和在线算法(RMQ+dfs)).(poj1330)(3)双端队列和它的应用(维护一个单调的队列,常常在动态规划中起到优化状态转移的目的). (poj2823)(4)左偏树(可合并堆).(5)后缀树(非常有用的数据结构,也是赛区考题的热点).(poj3415,poj3294)四.搜索(1)较麻烦的搜索题目训练(poj1069,poj3322,poj1475,poj1924,poj2049,poj3426)(2)广搜的状态优化:利用M进制数存储状态、转化为串用hash表判重、按位压缩存储状态、双向广搜、A*算法.(poj1768,poj1184,poj1872,poj1324,poj2046,poj1482)(3)深搜的优化:尽量用位运算、一定要加剪枝、函数参数尽可能少、层数不易过大、可以考虑双向搜索或者是轮换搜索、IDA*算法. (poj3131,poj2870,poj2286)五.动态规划(1)需要用数据结构优化的动态规划.(poj2754,poj3378,poj3017)(2)四边形不等式理论.(3)较难的状态DP(poj3133)六.数学(1)组合数学.1.MoBius反演(poj2888,poj2154)2.偏序关系理论.(2)博奕论.1.极大极小过程(poj3317,poj1085)2.Nim问题.七.计算几何学.(1)半平面求交(poj3384,poj2540)(2)可视图的建立(poj2966)(3)点集最小圆覆盖.(4)对踵点(poj2079)八.综合题.(poj3109,poj1478,poj1462,poj2729,poj2048,poj333 6,poj3315,poj2148,poj1263)初期:一.基本算法:(1)枚举. (poj1753,poj2965) (2)贪心(poj1328,poj2109,poj2586)(3)递归和分治法. (4)递推.(5)构造法.(poj3295) (6)模拟法.(poj1068,poj2632,poj1573,poj2993,poj2996)二.图算法:(1)图的深度优先遍历和广度优先遍历.(2)最短路径算法(dijkstra,bellman-ford,floyd,heap+dijkstra)(poj1860,poj3259,poj1062,poj2253,poj1125,po j2240)(3)最小生成树算法(prim,kruskal)(poj1789,poj2485,poj1258,poj3026)(4)拓扑排序 (poj1094)(5)二分图的最大匹配 (匈牙利算法) (poj3041,poj3020)(6)最大流的增广路算法(KM算法). (poj1459,poj3436)三.数据结构.(1)串 (poj1035,poj3080,poj1936)(2)排序(快排、归并排(与逆序数有关)、堆排)(poj2388,poj2299)(3)简单并查集的应用.(4)哈希表和二分查找等高效查找法(数的Hash,串的Hash)(poj3349,poj3274,POJ2151,poj1840,poj2002,po j2503)(5)哈夫曼树(poj3253)(6)堆(7)trie树(静态建树、动态建树) (poj2513)四.简单搜索(1)深度优先搜索(poj2488,poj3083,poj3009,poj1321,poj2251)(2)广度优先搜索(poj3278,poj1426,poj3126,poj3087.poj3414)(3)简单搜索技巧和剪枝(poj2531,poj1416,poj2676,1129)五.动态规划(1)背包问题. (poj1837,poj1276)(2)型如下表的简单DP(可参考lrj的书 page149):1.E[j]=opt{D+w(i,j)}(poj3267,poj1836,poj1260,poj2533)2.E[i,j]=opt{D[i-1,j]+xi,D[i,j-1]+yj,D[i-1][j-1 ]+zij} (最长公共子序列)(poj3176,poj1080,poj1159)3.C[i,j]=w[i,j]+opt{C[i,k-1]+C[k,j]}.(最优二分检索树问题)六.数学(1)组合数学:1.加法原理和乘法原理.2.排列组合.3.递推关系.(POJ3252,poj1850,poj1019,poj1942)(2)数论.1.素数与整除问题2.进制位.3.同余模运算.(poj2635, poj3292,poj1845,poj2115)(3)计算方法.1.二分法求解单调函数相关知识.(poj3273,poj3258,poj1905,poj3122)七.计算几何学.(1)几何公式.(2)叉积和点积的运用(如线段相交的判定,点到线段的距离等). (poj2031,poj1039)(3)多边型的简单算法(求面积)和相关判定(点在多边型内,多边型是否相交)(poj1408,poj1584)(4)凸包. (poj2187,poj1113)。

二分法模板

二分法模板

二分法模板二分法是指根据函数的单调性,每次将搜索区间缩小一半的算法。

在实际应用中,二分法通常用于查找有序数组中的某个元素,或者求解某个函数的零点或者极值等问题。

以下是二分法的模板:```python。

def binary_search(l, r):。

while l < r:。

mid = (l + r) // 2。

if check(mid):。

r = mid。

else:。

l = mid + 1。

return l # 如果是查找最大值,则返回 r。

# 下面是一个 check 函数的例子,可以根据具体需求进行修改。

def check(x):。

if x >= target:。

return True。

else:。

return False。

```。

使用二分法需要注意以下几点:1.对于有序数组的查找,初始时搜索区间是整个数组。

2. 不同于其他搜索算法,二分法是通过检查中点元素的取值来缩小搜索区间的,因此 check 函数中需要根据具体情况判断 mid 的取值应该向左还是向右移动。

3.如果需要查找最大值,则需要将最终返回的值改为r。

例子:在一个有序数组中查找某个元素的下标。

如果查找到了,返回下标;否则返回-1。

```python。

def binary_search(arr, target):。

l, r = 0, len(arr) - 1。

while l <= r: # 注意此处使用了等号,因为需要判断 l=r 的情况。

mid = (l + r) // 2。

if arr[mid] == target:。

return mid。

elif arr[mid] < target:。

l = mid + 1。

else:。

r = mid - 1。

return -1。

arr = [1, 3, 5, 7, 9]。

target = 5。

print(binary_search(arr, target)) # 输出 2。

数据结构-7顺序查找与二分查找

数据结构-7顺序查找与二分查找

i=m+1=8,j=8, m=(i+j)/2=8。 r[m]>k : 在左半部分继续查找。
i=8, j=m-1=7 ,
i>j: 查找失败
存储结构
key info 0 1 k1 2 k2 3 k3
…………
n kn
typedef struct { keytype key; ………….
} elemtype;
分块有序表的结构可以分为两部分: 1、线性表本身是顺序存储结构 2、再建立一个索引表,线性表中每个子表建立一个索引节点
。索引节点包括两部分:一是数据域,一是指针域。数据域存 放对应子表中的最大元素值,指针域用于指示子表第一个元素 的在整个表中序号。
分块查找
template<class T> struct indnode {
key=32
d (1) 27
i=1
d (2) 36
i=2
d (3) 32i=3 Nhomakorabead (4) 18
此时d(i)=key,数组中的第3个位置
如果输入查找的元素值key=22
d (1) 27 i=1
d (2) 36 i=2
d (3) 32 i=3
d (4) 18
i=4 i=5 此时i等于5,超过数组中元素个数,找不到
T key; int k; };
上图查找过程:首先查找索引表,确定查找的子表,然后再相应的子表中 应顺序表查找法查找。
• int blksearch(record r[],index idx[],keytype key)
•{
• int i=0,j;
• while(i<idxN)
•{
• if(key<=idx[i].key){
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

二分搜索需要注意开闭区间的问题,限制条件和边界要保持配对:low<=high ,low = mid +1 ,high = mid-1。

二分搜索的模板如下:
// 二分搜索
int BinarySearch(int *num, int key, int low, int high)
{
int mid ;
while(low <= high) //切记:条件是<= ,很多次都不小心写成了< ,导致了N 多W A
{
mid = (low + high)>>1;
if(num[mid] == key)
return mid;
else if(num[mid] < key)
low = mid + 1;
else
high = mid -1;
}
return low; //查找不成功时,返回应该插入的位置,或者直接返回-1,表示查找失败也是可以的
}
二分搜索的扩展:对已排好序的数组A,一般来说可用二分查找可以很快找到。

现有一特殊数组A[],它是循环递增的,如A[]={ 17 19 20 25 1 4 7 9},试在这样的数组中找一元素x,看看是否存在。

请写出你的算法,必要时可写伪代码,并分析其空间、时间复杂度。

对于循环有序的数组,它是循环递增的,例如:A[]={ 17 19 20 25 1 4 7 9},也可以使用二分搜索:每次将数组分为2部分,一个是单调递增的,一个是循环递增的。

如果是单调递增的话直接使用朴素的二分搜索,如果是循环递增的话继续使用特殊二分搜索下去。

思路分析:
在一个数组中检索一个元素,最普通的算法就是时间复杂度为O(n)的顺序检索。

要降低时间复杂度,并结合循环递增数组的元素已有一定程度顺序的性质,很容易想到二分查找。

我最初的想法是:朴素的二分查找在是下标区间[0 n-1]内进行二分,那么利用循环递增的性质,我们可以在数组的有效下标区间[0 n-1]的一个偏移区间[r+1 n+r-1]里进行二分(其中r是上述循环递增数组定义中的那个分界下标r)。

但是,这个想法的一个最大问题是:给定一个循环递增数组,我如何去确定其分界下标r?最明显的做法就是顺序扫描一遍数组,然后确定其分界下标r。

但是,既然你都扫描一遍了,也就能确定检索元素是否在该数组中了,何必再去利用分界下标r去检索呢?!
上述想法不成功,我们再去深入地去思考二分查找方法的一些原理特性。

在一个严格递增的数组中,我们将要检索的元素和数组中间的元素进行比较,然后根据要检索的元素与数组中间的元素的大小关系来确定该元素落在那个范围内,然后递归地在该范围内进行检索。

现在在循环递增数组中,我们不能简单地通过与数组中间元素的大小关系来确定要检索的元素所落在的区间范围。

要确定范围,我们可以再加上要检索的元素与数组两端的元素的大小
关系。

循环递增数组有这么一个性质:以数组中间元素将循环递增数组划分为两部分,则一部分为一个严格递增数组,而另一部分为一个更小的循环递增数组。

当中间元素大于首元素时,前半部分为严格递增数组,后半部分为循环递增数组;当中间元素小于首元素时,前半部分为循环递增数组;后半部分为严格递增数组。

记要检索的元素为key,数组的首元素为a[low],中间元素为a[mid],末尾元素为a[high]。

则当key不等于a[mid] 时,
1、a[mid] > a[low],即数组前半部分为严格递增数组,后半部分为循环递增数组时,若key小于a[mid]并且不小于a[low]时,则key落在数组前半部分;否则,key落在数组后半部分。

2、a[mid] < a[high],即数组前半部分为循环递增数组,后半部分为严格递增数组时,若key大于a[mid]并且不大于a[high]时,则key落在数组后半部分;否则,key落在数组前半部分。

通过上面利用数组首元素,中间元素和末尾元素确定要检索的元素所在范围,我们就可以使用修改后的二分查找算法了。

实现代码如下:
// 改进后的二分搜索
int Search(int A[],int n, int num)
{
int left = 0 ;
int right = n - 1 ;
int mid = 0 ;
int pos = -1 ; //返回-1,表示查找失败
while(left <= right)
{
mid = (left + right)/2 ;
if (A[mid] == num)
{
pos = mid ;
break;
}
if (A[left] <= A[mid]) //前半部分是严格递增的,后半部分是一个更小的循环递增数组
{
if(A[left] <= num && num < A[mid] )
{
right = mid - 1 ;
}
else
{
left = mid + 1 ;
}
}
else //后半部分是严格递增的,前半部分是一个更小的循环递增数组
{
if ( A[mid] < num && num <= A[right])
{
left = mid + 1 ;
}
else
{
right = mid - 1 ;
}
}
}
return pos;
}。

相关文档
最新文档