您的位置:首页 > 其它

二分查找排序

2013-10-30 22:08 288 查看
  二分查找算法,是在大学阶段学习的基础性算法。算法思想简单,但要写出一个正确的二分查找算法并不简单,从1946年提出,到1962年才完成一个正确的二分查找排序算法。二分查找排序算法的变种,也常常出现在各个IT公司的面试题中。本文总结资料尝试给出一个“正确”的二分查找算法,最后给出一个二分查找排序的变种问题。

  1. 经典二分查找排序的算法:

int BinarySearch(int* array, int n, int x)
{
assert((array != NULL) && (0 <= n));

int low = 0;
int high = n -1;

while (low <= high)
{
int mid = low + ((high - low) >> 1);
if (array[mid] == x)
{
return mid;
}
if (x > array[mid])
{
low = mid + 1;
}
else
{
high = mid -1;
}
}
return -1;
}


  可能需要关注细节问题:

  1)循环条件

  在第8行,循环的条件设置成 low <=high。如果设置成low<high,是存在问题的:当只有数组只有一个元素,并且该元素就是需要查找的元素时,算法返回错误的值-1,查找失败。

  2)求中间元素

  在第10行,求中间元素使用的代码:mid = low + ((high - low) >> 1)。一些书籍中给出的是:mid = (high + low) >> 1,如果high+low很大时,会造成溢出。这种情况出现的概率较小,但是为了程序适应比较恶劣条件,使用第10行代码求中间元素就显得有必要了。

(ps:上面的代码可能还存在带完善的地方,欢迎拍砖。。。)

  2. 二分查找排序算法的变种

  问题描述:已知一个有序的数组a
,循环左移k位(k<N)后得到新的数组b
,在这个新的数组中查找元素x。例如:数组 a
= {1, 3, 5, 7, 9, 10},循环左移2位后变成数组b
= {5, 7, 9, 10, 1, 3},在这个新的数组上查找某个元素x。

  上题是我在面试中问道的问题,比较庆幸的是我在《剑指offer》一书中碰到了类似的一题,书中需要找出数组b
最小的最小元素,因此能比较迅速的解决了这个问题。解决问题的思路和《剑指offer》提供的思路一致。

  解题思路:数组b
中存在着两个部分有序的子数组,b1:{5, 7, 9, 10}和b2:{1, 3},其中b1中的元素均大于b2中的元素。在使用二分查找算法时,中间元素mid必定落入b1或者b2某个递增序列中,具体解决步骤如下:

  Init: low = 0, high = N-1, mid = b[low + (high - low) >> 1]

  step1: 求出数组b的中间元素mid, 如果mid == x,则返回成功,否则进入步骤step2。

  step2: if(a[low]<mid),mid落入b1数组,此时:

         1) if (a[low]<x<mid), x在有序区间[low, mid),则将high = mid -1

         2) 否则,x落入区间(mid, high],则将low = mid +1

      else mid落入b2数组,此时:

         1)if (mid< x< b[high]),x在有序区间(mid, high],则将low = mid + 1

         2)否则, x落入区间[low, mid),则将hign = mid -1

  step3: if(low <= hign) 继续步骤step1,否则返回查找失败

具体的代码如下:

int rotate_array_search(int a[], int n, int x)
{
int low = 0;
int high = n-1;
while(low <= high)
{
int mid = low + ((high - low) >> 1);

if(a[mid] == x)
return mid;

if(a[mid] >= a[low])
{
if(x < a[mid] && x >= a[low])
{
high = mid -1;
}
else
{
low = mid + 1;
}
}
else
{
if(x > a[mid] && x <= a[high])
{
low = mid + 1;
}
     else
{
high = mid -1;
}
}
}
return -1; // 查找失败,则返回-1
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: