- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
二分搜索及其扩展(循环递增数组的搜索)
二分搜索需要注意开闭区间的问题,限制条件和边界要保持配对:low=high , low = mid +1? ,high = mid-1。二分搜索的模板如下:
// 二分搜索
int BinarySearch(int *num, int key, int low, int high)
{
int mid ;
while(low = high) //切记:条件是 = ,很多次都不小心写成了 ,导致了N多WA
{
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[l
原创力文档


文档评论(0)