一.二分查找的原理
就是这个原理,跟中间的比的话,每次都可以排除一半.
上次在分治法里面我们用的递归实现,现在我们就普通的方法来实现.
二.二分查找的实现
为了能适应多种类型的查找,我们用到了函数指针做为参数.
这里我们写了int类型和char类型的比较.
相减来判断两个值的大小.
二分查找的参数:
- 数组用的void*可以接受不同类型的数组
- len是数组的长度
- elemSize是元素的长度,因为
void*类型的不能用下标访问,我们只能通过指针的相加去访问到目标数组元素
,因为不同类型的数组,步长不一,需要传入这个. - search是查找目标
- int (compare)(const voidkey1,const void*key2)是函数指针,传入不同的函数,指向不同的功能.
如果目标值等于中间的值,我们就返回这个下标,大于的话,左边的起始位置改变,小于的话,右边的位置改到中间位置的前一个.一直循环,直到left不小于right时.
在void*类型的数组中找目标元素的位置用的是指针加步长.就是字节的长度.
三.完整代码
#include <iostream>
using namespace std;
int int_compare(const void* key1, const void* key2)
{
const int* ch1 = (const int*)key1;
const int* ch2 = (const int*)key2;
return (*ch1 - *ch2);
}
int char_compare(const void* key1, const void* key2)
{
const char* ch1 = (const char*)key1;
const char* ch2 = (const char*)key2;
return (*ch1 - *ch2);
}
int BinarySearch(void* sorted, int len, int elemSize, void* search, int (*compare)(const void* key1, const void* key2))
{
int left = 0, right = 0, middle = 0;
right = len - 1;
while (left<=right)
{
int ret = 0;
middle = left + (right - left) / 2;
ret = compare((char*)sorted + (middle * elemSize), search);
if (ret == 0)
{
return middle;
}
else if (ret > 0)
{
right = middle - 1;
}
else
{
left = middle + 1;
}
}
return -1;
}
int main()
{
int arr[] = { 1,3,7,9,11 };
int len = sizeof(arr) / sizeof(arr[0]);
int search[] = { -1,0,1,7,2,11,12 };
int lens = sizeof(search) / sizeof(search[0]);
for (int i = 0; i < lens; i++)
{
int index = BinarySearch(arr, len, sizeof(int), &search[i], int_compare);
printf("searching %d,index: %d\n", search[i], index);
}
printf("字符查找测试开始...\n");
char arr1[] = { 'a','c','d','f','j' };
char search1[] = { '0','a','e','j','z' };
for (int i = 0; i < sizeof(search1) / sizeof(search1[0]); i++)
{
int index = BinarySearch(arr1, sizeof(arr1) / sizeof(arr1[0]), sizeof(char), &search1[i], char_compare);
printf("searching %c,index: %d\n", search1[i], index);
}
system("pause");
return 0;
}
运行结果:
返回-1的就是没找到,其他的都是下标的位置.
2024年8月20日15:57:16