飞道的博客

二分查找——“C”

336人阅读  评论(0)

各位CSDN的uu们你们好呀,欢迎来到小雅兰的课堂,今天我们的内容是复习之前的内容,并把之前的内容的一些习题一起来做一做,现在,就让我们进入二分查找的世界吧

首先,我们介绍的题目就是二分查找,也叫折半查找

我们定义了一个整型数组,为1 2 3 4 5 6 7 8 9 10,这个数组所有元素的下标为0 1 2 3 4 5 6 7 8 9,然后定义下标为0的元素为left,定义下标为9的元素为right,中间元素为mid 

 我们先假设要查找的元素就是7,那么就可以写出这样一个式子:mid=(left+right)/2;然后再进行二分查找,由下图可知,用二分查找的方式找到7这个元素最多只需要查找4次这样的效率远比遍历的方法的效率要高

下面,我们来用代码来实现一下此功能吧


  
  1. #include<stdio.h>
  2. int main()
  3. {
  4. int arr[]={ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  5. //0,1,2,3,4,5,6,7,8,9
  6. int k= 7; //k是要查找的数字
  7. int sz= sizeof(arr)/ sizeof(arr[ 0]);
  8. //折半查找(二分查找),前提是数组有序
  9. int left= 0;
  10. int right=sz -1;
  11. int flag= 0; //一个标记变量
  12. while(left<=right)
  13. {
  14. int mid=(left+right)/ 2;
  15. if(arr[mid]<k)
  16. {
  17. left=mid+ 1;
  18. }
  19. else if(arr[mid]>k)
  20. {
  21. right=mid -1;
  22. }
  23. else
  24. {
  25. printf( "找到了,下标是:%d\n",mid);
  26. flag= 1;
  27. break;
  28. }
  29. }
  30. if(flag== 0)
  31. {
  32. printf( "找不到\n");
  33. }
  34. return 0;
  35. }

然后,我们来运行一些此代码

 写到这里,我们不禁会想起一个问题:如果这个数组非常非常大怎么办?

如果这个数组非常非常大,left和right非常大,left没有超出整型范围的最大值,right也没有超过整型范围的最大值,但left+right的和超出了整形范围的最大值,就会造成溢出现象,溢出之后的数据再除以2,就不是平均值了,所以mid=(left+right)/2这样的写法还是存在潜在风险

我们可以这样写:mid=left+(right-left)/2;


  
  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #include<stdio.h>
  3. int main()
  4. {
  5. int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  6. //0,1,2,3,4,5,6,7,8,9
  7. int k = 7; //k是要查找的数字
  8. scanf( "%d", &k);
  9. int sz = sizeof(arr) / sizeof(arr[ 0]);
  10. //折半查找(二分查找),前提是数组有序
  11. int left = 0;
  12. int right = sz - 1;
  13. int flag = 0; //一个标记变量
  14. while (left <= right)
  15. {
  16. int mid = left+(right-left) / 2;
  17. if (arr[mid] < k)
  18. {
  19. left = mid + 1;
  20. }
  21. else if (arr[mid] > k)
  22. {
  23. right = mid - 1;
  24. }
  25. else
  26. {
  27. printf( "找到了,下标是:%d\n", mid);
  28. flag = 1;
  29. break;
  30. }
  31. }
  32. if (flag == 0)
  33. {
  34. printf( "找不到\n");
  35. }
  36. return 0;
  37. }

最后的结果也是非常正确的

 我们再来研究研究,前段时间我们学习了“函数”这一知识点,那我们也是可以封装一个函数来实现此代码的,那好吧,一起来实操一下


  
  1. #include<stdio.h>
  2. int binary_search(int arr[],int k,int sz)
  3. {
  4. int left= 0;
  5. int right=sz -1;
  6. while(left<=right)
  7. {
  8. int mid=left+(right-left)/ 2;
  9. if(arr[mid]>k)
  10. {
  11. right=mid -1;
  12. }
  13. else if(arr[mid]<k)
  14. {
  15. left=mid+ 1;
  16. }
  17. else
  18. {
  19. return mid;
  20. }
  21. }
  22. return -1;
  23. }
  24. int main()
  25. {
  26. int arr[]={ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  27. int k= 0;
  28. scanf( "%d",&k);
  29. int sz= sizeof(arr)/ sizeof(arr[ 0]);
  30. //找到了就返回下标,找不到就返回-1
  31. int ret= binary_search(arr,k,sz);
  32. if(ret== -1)
  33. {
  34. printf( "找不到\n");
  35. }
  36. else
  37. {
  38. printf( "找到了,下标是:%d\n",ret);
  39. }
  40. return 0;
  41. }

好啦,用封装函数的方法也实现啦

 那么,可能又会有人突发奇想,说:“可不可以把sz放在函数内部来求呢?”这个答案当然是否定

它的代码是这个样子


  
  1. #include<stdio.h>
  2. int binary_search(int arr[], int k)
  3. {
  4. int left = 0;
  5. int sz = sizeof(arr) / sizeof(arr[ 0]);
  6. int right = sz - 1;
  7. while (left <= right)
  8. {
  9. int mid = left + (right - left) / 2;
  10. if (arr[mid] > k)
  11. {
  12. right = mid - 1;
  13. }
  14. else if (arr[mid] < k)
  15. {
  16. left = mid + 1;
  17. }
  18. else
  19. {
  20. return mid;
  21. }
  22. }
  23. return -1;
  24. }
  25. int main()
  26. {
  27. int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  28. int k = 0;
  29. scanf( "%d", &k);
  30. //找到了就返回下标,找不到就返回-1
  31. int ret = binary_search(arr, k);
  32. if (ret == -1)
  33. {
  34. printf( "找不到\n");
  35. }
  36. else
  37. {
  38. printf( "找到了,下标是:%d\n", ret);
  39. }
  40. return 0;
  41. }

你运行起来,会发现,无论输入2之后的任意数字,输出的结果都是找不到

 

 因为:arr是数组名,进行函数传参的时候,传进来的是首元素的地址,在binary_search()函数的形参中,arr实质上是一个指针,sizeof(arr)只是算出来这个首元素的地址所占空间大小,sizeof(arr[0])是这个元素占的空间大小,两者相除必为1.

而在主函数中求sz,sizeod(数组名) 计算的是整个数组的大小

    sizeof内部单独放一个数组名,数组名表示整个数组


好啦,小雅兰今天的内容就到这里啦,今天的内容可能比较简单,也很少,但是小雅兰有认真在学噢!!!uu们加油呀


转载:https://blog.csdn.net/weixin_74957752/article/details/128749022
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场