数据结构&算法 二分查找

  • 二分查找

    二分查找是一种运行时间复杂度为O(log n)的快速搜索算法。这种搜索算法基于分治法的原理。为了使该算法正常工作,数据收集应采用排序形式。二分查找通过比较集合中最中间的项来查找特定项。如果发生匹配,则返回项目的索引。如果中间项目大于该项目,则在中间项目左侧的子数组中搜索该项目。否则,将在中间项目右侧的子数组中搜索该项目。该过程同样在子数组上继续进行,直到子阵列的大小减小到零为止。
  • 二分查找如何工作?

    为了使二分查找有效,必须对目标数组进行排序。我们将通过一个图形示例来学习二分查找的过程。以下是我们的排序数组,让我们假设我们需要使用二分查找来搜索值31的位置。
    binarysearch
    首先,我们将使用此公式确定数组的一半-
    
    mid = low + (high - low) / 2
    
    就是(0 + 9)/ 2 = 4(4.5的整数值)。因此,4是数组的中间。
    binarysearch
    现在,我们将存储在位置4的值与要搜索的值(即31)进行比较。我们发现位置4的值是27,这不是匹配项。由于该值大于27,并且我们有一个已排序的数组,因此我们也知道目标值必须在数组的右边。
    binarysearch
    我们将低点更改为中间+1,然后再次找到新的中间值。
    
    low = mid + 1
    mid = low + (high - low) / 2
    
    现在我们的新中数是7。我们将存储在位置7的值与目标值31进行比较。
    binarysearch
    存储在位置7的值不是匹配项,而是大于我们所寻找的值。因此,该值必须位于此位置的左边。
    binarysearch
    因此,我们再次计算中点。这次是5。
    binarysearch
    我们将存储在位置5的值与目标值进行比较。我们发现这次匹配了。
    binarysearch
    我们得出结论,目标值31存储在位置5。二分查找将可搜索的项目减半,从而将进行比较的次数减少到非常少的数目。
    伪代码
    
    Procedure binary_search
       A ← sorted array
       n ← size of array
       x ← value to be searched
    
       Set lowerBound = 1
       Set upperBound = n 
    
       while x not found
          if upperBound < lowerBound 
             EXIT: x does not exists.
       
          set midPoint = lowerBound + ( upperBound - lowerBound ) / 2
          
          if A[midPoint] < x
             set lowerBound = midPoint + 1
             
          if A[midPoint] > x
             set upperBound = midPoint - 1 
    
          if A[midPoint] = x 
             EXIT: x found at location midPoint
       end while
       
    end procedure
    
    用C编程语言实现二分查找-
    
    #include <stdio.h>
    
    #define MAX 20
    
    // array of items on which linear search will be conducted. 
    int intArray[MAX] = {1,2,3,4,6,7,9,11,12,14,15,16,17,19,33,34,43,45,55,66};
    
    void printline(int count) {
       int i;
      
       for(i = 0;i < count-1;i++) {
          printf("=");
       }
      
       printf("=\n");
    }
    
    int find(int data) {
       int lowerBound = 0;
       int upperBound = MAX -1;
       int midPoint = -1;
       int comparisons = 0;      
       int index = -1;
      
       while(lowerBound <= upperBound) {
          printf("Comparison %d\n" , (comparisons +1) );
          printf("lowerBound : %d, intArray[%d] = %d\n",lowerBound,lowerBound,
             intArray[lowerBound]);
          printf("upperBound : %d, intArray[%d] = %d\n",upperBound,upperBound,
             intArray[upperBound]);
          comparisons++;
        
          // compute the mid point
          // midPoint = (lowerBound + upperBound) / 2;
          midPoint = lowerBound + (upperBound - lowerBound) / 2;  
        
          // data found
          if(intArray[midPoint] == data) {
             index = midPoint;
             break;
          } else {
             // if data is larger 
             if(intArray[midPoint] < data) {
                // data is in upper half
                lowerBound = midPoint + 1;
             }
             // data is smaller 
             else {
                // data is in lower half 
                upperBound = midPoint -1;
             }
          }               
       }
       printf("Total comparisons made: %d" , comparisons);
       return index;
    }
    
    void display() {
       int i;
       printf("[");
      
       // navigate through all items 
       for(i = 0;i < MAX;i++) {
          printf("%d ",intArray[i]);
       }
      
       printf("]\n");
    }
    
    void main() {
       printf("Input Array: ");
       display();
       printline(50);
      
       //find location of 1
       int location = find(55);
    
       // if element was found 
       if(location != -1)
          printf("\nElement found at location: %d" ,(location+1));
       else
          printf("\nElement not found.");
    }
    
    尝试一下
    如果我们编译并运行上述程序,它将产生以下结果-
     
    Input Array: [1 2 3 4 6 7 9 11 12 14 15 16 17 19 33 34 43 45 55 66 ]
    ==================================================
    Comparison 1
    lowerBound : 0, intArray[0] = 1
    upperBound : 19, intArray[19] = 66
    Comparison 2
    lowerBound : 10, intArray[10] = 15
    upperBound : 19, intArray[19] = 66
    Comparison 3
    lowerBound : 15, intArray[15] = 34
    upperBound : 19, intArray[19] = 66
    Comparison 4
    lowerBound : 18, intArray[18] = 55
    upperBound : 19, intArray[19] = 66
    Total comparisons made: 4
    Element found at location: 19