• 二分查找排序


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

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

     1 int BinarySearch(int* array, int n, int x)
     2 {
     3     assert((array != NULL) && (0 <= n));
     4 
     5     int low = 0;
     6     int high = n -1;
     7 
     8     while (low <= high)
     9     {
    10         int mid = low + ((high - low) >> 1);
    11         if (array[mid] == x)
    12         {
    13             return mid;
    14         }
    15         if (x > array[mid])
    16         {
    17             low = mid + 1;
    18         }
    19         else
    20         {
    21             high = mid -1;
    22         }
    23     }
    24     return -1;
    25 }

      可能需要关注细节问题:

      1)循环条件

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

      2)求中间元素

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

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

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

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

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

      解题思路:数组b[N]中存在着两个部分有序的子数组,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,否则返回查找失败

     具体的代码如下:

     1 int rotate_array_search(int a[], int n, int x)
     2 {
     3   int low = 0;
     4   int high = n-1; 
     5   while(low <= high) 
     6   {
     7     int mid = low + ((high - low) >> 1); 
    8 if(a[mid] == x) 9 return mid;
    10 if(a[mid] >= a[low]) 11 { 12 if(x < a[mid] && x >= a[low]) 13 { 14 high = mid -1; 15 } 16 else 17 { 18 low = mid + 1; 19 } 20 } 21 else 22 { 23 if(x > a[mid] && x <= a[high]) 24 { 25 low = mid + 1; 26 }
         else 27 { 28 high = mid -1; 29 } 30 } 31 } 32 return -1; // 查找失败,则返回-1 33 }
  • 相关阅读:
    调试JavaScript/VB Script脚本程序(ASP篇)
    成功接收来自Internet的邮件必须要做到的条件
    (转)Ext与.NET超完美整合 .NET开发者的超级优势
    如何防垃圾邮件用你的邮件服务器转发
    记录书籍名称
    GRE网站
    JAVA线程的缺陷
    【让这些电影给你“治病”】
    zoj题目分类
    Oracle to_char格式化函数
  • 原文地址:https://www.cnblogs.com/wangbogong/p/3392649.html
Copyright © 2020-2023  润新知