循环遍历
今天学习了使用for循环来遍历一个数组从而找到自己想要的那个值
如下
#include <stdio.h>
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // 给定一个有序的数组
int key; // 创建一个可输入的变量
int i = 0; // 创建一个条件的变量
int sz = sizeof(arr) / sizeof(arr[0]); // 使用关键字sizeof来计算整个数组的大小
scanf("%d", &key); // 使用scanf来输入想要查找的数
for (i = 0; i < sz; i++)// 表达式里声明了i=0 因为需要实现遍历整个数组所以让i<整个数组的大小 如果第一次没找到那么i++直到找到或者i=sz
{
if (arr[i] == key) // 当for在某一次循环的时候找到了我们输入的key值那么就执行if下的代码段
{
printf("找到了位于数组下标%d\n", i); // 提示找到了 位于数组下标为哪里的位置
break; // 找到后希望它停止循环所以加上break
}
if (!found) // 如果遍历了整个数组没找到则提示没找到
{
printf("没找到");
}
}
return 0;
}
但是这样如果输入的是10程序则需要遍历10遍才能得出结果这样效率是非常慢的有没有快点的方法让查找的速度变快呢?
二分查找
在b站的比特c语言的课程中就让我学会了二分查找 如下
#include <stdio.h>
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // 给定一个有序的数组
int key = 10; // 想查找的数
int sz = sizeof(arr) / sizeof(arr[0]); // 使用关键字sizeof来计算整个数组的大小
int left = 0; // 数组第一个元素下标
int right = sz - 1; // 数组最后一个元素下标
while (left <= right)
{
int mid = (left + right) / 2; // 中间元素下标
if (arr[mid] < key) // 使用中间元素下标来跟我们想要查找的数对比如果小于我们想要查找的元素
{
left = mid + 1; // 这样我们的数组初始元素下标就变成了中间元素的下标了
}
else if (arr[mid] > key) // 如果大于我们想要查找的元素那么我们就使数组最后一个下标-1
{
right = mid - 1;
}
else // 第三种情况是等于相当于找到了 但是这种只是进行了一次查找 如果第一次没找到我希望它进行下一次寻找所以if外边需要加一个循环
{
printf("元素位置结果%d", mid);
break; // 找到了应该终止循环
}
}
if (left > right)
{
printf("查询无果");
}
return 0;
}
基本原理是
计算当前查找范围的中间位置 mid = (left + right) / 2。
比较中间位置的元素 arr[mid] 与目标值 key:
如果 arr[mid] == key,则找到了目标值,返回 mid。
如果 arr[mid] < key,说明目标值在右半部分,更新左边界 left = mid + 1。
如果 arr[mid] > key,说明目标值在左半部分,更新右边界 right = mid - 1。
重复上述步骤,直到找到目标值或查找范围为空(即 left > right)
如果找到了目标值,返回其索引。
如果查找范围为空,说明目标值不存在,返回一个标识值(如 -1)
结论
优点
二分查找的时间复杂度是 O(log n),因为每次查找都会将搜索范围减半。在处理大规模有序数据时,二分查找比线性查找(O(n))更为高效
缺点
但是缺点是条件比较苛刻必须是有序的数组