二分查找要求所查找的顺序表必须是有序的,其思想非常简单。定义left为顺序表最左端元素位置,right为顺序表右端元素位置。定义mid = (left + right) / 2,即顺序表的中间位置,然后用所查找的值与mid所在位置处的值比较,由于列表有序,若所查找的值比mid小,则只需在表的前半部分查找,否则只需在表的后半部分查找(若第一次比较就发现两值相等则直接返回当前值所在的位置),以此类推,直至查找到所寻找的值或确定所查找的值不在该列表内为止(即查找失败)。代码如下:
```c
#include<stdio.h>
int Binary_Search(int* a, int size, int val)
{
int pos = -1;//pos返回查找到的值的位置
if (a == nullptr || size < 1)//数组合法性检查
{
return pos;
}
int left = 0;
int right = size - 1;
while (left <= right)//当左端元素位置不等于右边元素位置时反复查找
{
int mid = (left + right) / 2;
if (val < a[mid])//若所查找值小于中间值,在前半部分查找
{
right = mid - 1;
}
else if (val > a[mid])//若所查找值大于中间值在后半部分查找
{
left = mid + 1;
}
else
{
pos = mid;//若已找到则终止循环
break;
}
}
return pos;//返回查找到的值所在位置
}
int main()
{
const int n = 10;
int ar[n] = {12,23,34,45,56,67,78,89,90,100};
int idex, value;
printf("请输入要查询的值:");
scanf_s("%d", &value);
idex = Binary_Search(ar, n, value);//idex获取所查找的值得位置,即pos
printf("%d", idex);//若idex = -1,要么数组不合法,要么查找失败。在数组合法的前提下即可知道查找失败
return 0;
}
那如果一个数组里有多个连续重复的值,我们想找到连续重复值中下标最小的应该怎么办呢?我们只需对else语句略作修改`
else
{
while (mid > left && a[mid - 1] == val)//在不越界的前提下后一个值与前一个值相等
{
--mid;//下标减一
}
pos = mid;//若已找到则终止循环
break;
}
完整代码如下:
#include<stdio.h>
int Binary_Search(int* a, int size, int val)
{
int pos = -1;//pos返回查找到的值的位置
if (a == nullptr || size < 1)//数组合法性检查
{
return pos;
}
int left = 0;
int right = size - 1;
while (left <= right)//当左端元素位置不等于右边元素位置时反复查找
{
int mid = (left + right) / 2;
if (val < a[mid])//若所查找值小于中间值,在前半部分查找
{
right = mid - 1;
}
else if (val > a[mid])//若所查找值大于中间值在后半部分查找
{
left = mid + 1;
}
else
{
while (mid > left && a[mid - 1] == val)//在不越界的前提下后一个值与前一个值相等
{
--mid;//下标减一
}
pos = mid;//若已找到则终止循环
break;
}
}
return pos;//返回查找到的值所在位置
}
int main()
{
const int n = 20;
int ar[n] ={12,12,23,23,34,45,45,45,56,67,78,89,90,100,100,101 };
int idex, value;
printf("请输入要查询的值:");
scanf_s("%d", &value);
idex = Binary_Search(ar, n, value);//idex获取所查找的值得位置,即pos
printf("%d", idex);//若idex = -1,要么数组不合法,要么查找失败。在数组合法的前提下即可知道查找失败
return 0;
}