Binary Search

Desktop

Binary Search


版权声明:本文为 cheng-zhi 原创文章,可以随意转载,但必须在明确位置注明出处!

Binary Search is a basic search algorithm. Its basic idea is each search is reduced by half of the data. Such as,using Binary Search to search 2 in this table :

1. First  search index = (0 + 10) / 2 = 5,and 2 < 5,then search [0, 4]
2. Second search index = (0 + 4)  / 2 = 2, and 2 == 2,find it !

Before you use Binary Search,you must be know below points :

1. Binary Search O(n) = O(log2n)
2. The set of searchs it must be ordered(Ascending or Descneding),such as above array table. 
3. It applies to infrequently changing and finding frequent ordered lists.

Now,we see the algorithm code.

Algorithm Code

I use C to coding,like below :

Array and division

Using arrays and division is the easiest way :

int *binary_search_common(int *array, int length, int key) {
  int low = 0;
  int mid = 0;
  int high = length - 1;

  while (low <= high) {
    mid = (high + low) / 2;
    printf("binary_search_common: mid = %d\n", mid);

    if (key < array[mid])
      high = mid - 1;
    else if (key > array[mid])
      low = mid + 1;
    else 
      return array + mid;   // Ok,find it !
  }

  // No find !
  return NULL;
}

Point and right shift

Using pointer and right shift instead of array and division to improve efficiency :

int *binary_search_improve(int *array, int length, int key) {
  int *low = array;
  int *mid = NULL;
  int *high = array + length - 1;

  while (low <= high) {
    mid = low + ((high - low) >> 1);
    printf("binary_search_improve: mid = %d\n", mid - low);

    if (key < *mid)
      high = mid - 1;
    else if (key > *mid)
      low = mid + 1;
    else 
      return mid;   // Ok,find it !
  }
  
  // No find !
  return NULL;
}

Recursive

I suggest you`d better use recursion to achieve it again :

int *binary_search_rec(int *array, int *low, int *high, int key) {
  if (low > high) 
    return NULL;    // No find !

  int *mid = low + ((high - low) >> 1);
  printf("binary_search_rec: mid = %d\n", mid - low);

  if (key < *mid)
    return binary_search_rec(array, low, mid - 1, key);
  else if (key > *mid)
    return binary_search_rec(array, mid + 1, high, key);
  else
    return mid; // Ok,find it !
}

TestCode

I use an order array as test data :

int main(int argc, char **argv) {
  if (argc < 2) {
    printf("Usage: ./a.out search_num:[0, 10]\n");
    exit(1);
  }

  int a[11] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  int key = atoi(argv[1]);
   
  int *find1 = binary_search_common(a, 11, key); 
  int *find2 = binary_search_improve(a, 11, key); 
  int *find3 = binary_search_rec(a, a, a + 11, key);
  
  printf("%d\n", *find1);
  printf("%d\n", *find2); 
  printf("%d\n", *find3);
  return 0;
}

Compile and run :

gcc binary_search.c
./a.out 2

binary_search_common: mid = 5
binary_search_common: mid = 2
binary_search_improve: mid = 5
binary_search_improve: mid = 2
binary_search_rec: mid = 5
binary_search_rec: mid = 2
2
2
2

Can be seen,we only need to find 2 times. But,for an ordered list,it is not the fastest algorithm. For example,finding 2 still takes 2 times,but actually we can find 2 only once !

Continue to see the faster algorithm below !

Interpolation Search

Interpolation Search and Binary Search basically the same,the only difference is how to calculate mid.

In Binary Search :

mid = low + ((high - low) >> 1);

But in Interpolation Search :

mid = low + (high - low) * ((double)(key - array[low]) / (array[high] - array[low]));

What is it ? look below :

We calculate the mid by the following proportional formula :

(mid - low) / (high - low) = (key - array[low]) / (array[high] - array[low])

->

mid = low + (high - low) * (key - array[low]) / (array[high] - array[low]);

But we must be add double to case type,because we need to let 0 < (key - array[low]) / (array[high] - array[low]) < 1if we do not case it to double,the expression will be zeor,so we must be case it to double :

// Case (key - array[low]) to double.
mid = low + (high - low) * ((double)(key - array[low]) / (array[high] - array[low]));

Point type,because point do not add to double,we need to case it to int so that it can add to point low :

mid = low + (int)((high - low) * ((double)(key - (*low)) / ((*high) - (*low))));

Interpolation Code

OK,now you only need to replace how to calculate the expression of mid can be achieved Interpolation Search :

int *binary_search_xxx(int *array, int length, int key) {
  ...
  while (low <= high) {
    // For array and division.
    mid = low + (high - low) * ((double)(key - array[low]) / (array[high] - array[low]));
    printf("binary_search_xxx: mid = %d\n", mid);

    // For point and >>
    mid = low + (int)((high - low) * ((double)(key - (*low)) / ((*high) - (*low))));
    printf("binary_search_xxx: mid = %d\n", mid - low);
  }
  ...
}

You can use the above code main function to test this algorithm,and the result like below :

gcc binary_search.c
./a.out 2

binary_search_common: mid = 2   // Note: We only need to search once !
binary_search_improve: mid = 2
binary_search_rec: mid = 2
2
2
2

This can be,thank you for reading.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • “孩子作业写的太慢,拖拖拉拉,磨磨蹭蹭,总是不能按时完成。” “即使你坐在他旁边,盯着他写,一笔一划指导他写,天天...
    俩千金的妈阅读 309评论 0 0
  • 17:43分,我说:大头,晚上你们家门口麻辣烫。她说:好,我等你。 结果,我坐着车晃晃悠悠走了一个...
    木兮日记阅读 145评论 0 3
  • 题记:小王子曾说过:“生活才不是生命荒唐的编号,生活的意义在于生活本身。”只要活着,就能体验到生命每个阶段不同的精...
    蓝色的海sunshine阅读 332评论 0 0
  • 作为一个N*N线不知名小写手,我曾经多次在微博上写过奇葩说,更有好几篇文章的取材来源于这个节目的辩题。我毫不掩饰地...
    维真阅读 4,467评论 1 11