二分法在有序数组中查找一个数

来源:互联网 发布:wow猎人 知乎 编辑:程序博客网 时间:2024/05/01 22:38

例:在一个有序数组{1,2,3,4,5,6,7,8,9,10}中查找元素7的下标

算法思想:

因为是有序数组,先查找中间下标的元素:

(1)如果该元素等于7,则返回中间下标,查找结束;         

(2)如果该元素大于7,则7必然在中间元素的右边部分,则缩小范围,在右半部分查找7,再计算右半部分的中间下标,转到(1)

(3)如果该元素下于7,则7必然在中间元素的左半部分,则缩小范围,在左半部分查找7,再计算左半部分的中间下标,转到(1)

程序代码1:首先先在主函数中将该算法实现

int main()
{
 int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
 int key = 7;
 int left = 0;
 int right = sizeof(arr) / sizeof(arr[0]) - 1;//计算数组元素最大下标
 while (left <= right)
 {
  int mid = left + (right - left) / 2;//防止溢出
  if (arr[mid] == key)
  {
   printf("找到啦,下标为:%d\n", mid);
   break;
  }
  else if (arr[mid] < key)
  {
   left = mid + 1;
  }
  else
  {
   right = mid - 1;
  }
 }
 if (left>right)
 {
  printf("没找到\n");
 }
 system("pause");
 return 0;
}

程序代码2:为了便于引用二分法,将该算法单独在一个函数中实现

int binary(int arr[], int key, int sz)
{
 int left = 0;//数组右下标
 int right = sz - 1;//数组左下标
 while (left <= right)
 {
  int mid = left + (right - left) / 2;//防止溢出
  if (arr[mid] == key)
  {
   //printf("找到啦,下标为:%d\n", mid);
   //break;
   return mid;
  }
  else if (arr[mid] < key)
  {
   left = mid + 1;
  }
  else
  {
   right = mid - 1;
  }
 }
 return -1;
}
int main()
{
 int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 10 };
 int key = 11;
 int sz = sizeof(arr) / sizeof(arr[0]);//数组元素个数
 int ret = binary(arr, key, sz);
 if (ret == -1)
 {
  printf("没找到\n");
 }
 else
 {
  printf("找到啦,下标为:%d\n", ret);
 }
 system("pause");
 return 0;
}

注意:当使用数组做参数时,数组名代表的是数组首元素的地址,所以要将数组元素个数一并传过去,这样才便于对整个数组进行操作,否则只能对数组首元素进行操作


程序代码3:当要求在数组的某个范围查找时,如在下标为3到8的元素之间查找某数,上述算法便不再使用

修改:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
 int search(int a[], int k, int left,int right);
 int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
 int k = 0;
 printf("请输入想要查找的数字:");
 scanf("%d", &k);
 int left = 0;//自主定义左右下标,将其传给search函数
 int right = sizeof(a) / sizeof(a[0])-1;
 int b=search(a,k,left,right);
 if (b != -1)
 {
  printf("该数字所在的下标为:%d\n", b);
 }
 else
 {
  printf("没找到\n");
 }
 system("pause");
 return 0;
}
int search(int a[], int k,int left,int right)
{
 int mid = 0;
 while (left<=right)
 {
  mid = left + (right - left)/2;//注意将该语句放在循环体内,这样才能不断地二分
  if (a[mid] > k)
  {
   right = mid-1;
  }
  else if (a[mid] < k)
  {
   left = mid+1;
  }
  else
  {
   return mid;
  }
 }
 return -1;
}


原创粉丝点击