今天起,我要对数据结构和基本的算法进行一些简单的复习,并在复习的基础上对其进行深入的挖掘。这篇文章先对二分查找进行一个简要的复习,在之后的文章中会对其进行深入的学习。
二分查找又叫折半查找,是最基本的几种查找算法之一。简单的看,二分法查找主要应用于在一个有序数列中进行元素的查找,其基本思路是,先用我们要查找的元素与这个有序数列中的中间位置的元素进行比较(在此我们姑且称这个元素为“中间位置元素”吧,至于这个元素怎么求我在后面会详细说明),如果相等,则返回这个“中间位置元素”的值;若待查找元素小于“中间位置元素”,我们就以中间位置元素为界,在中间位置元素的“左边”进行查找,当然,查找的方式和我们第一步所做的一样,还是将待查找元素与中间位置元素进行对比,不过要注意的是,这里的中间位置元素可不是最初的数列的中间位置的元素,而是在最初的数列的基础之上,以第一步的“中间位置元素”为界划分出来的左边的子数列的中间位置元素。那么如果待查找元素大于“中间位置元素”,我们在下一步的折半查找中就要在“中间位置元素”右侧的那部分子数列进行同样的二分操作。不管是在哪一侧的子数列进行查找,这样一遍一遍的划分查找,最后总会找到,除非你要找的数根本就没有在这个数列中。
说到这里,大概就可以解释得通为什么二分查找又叫折半查找了,从第一步的过程看,他就是把数列以位于中间位置的元素为界,分成左右两半,然后根据待查元素值与当前所在数组(注意我的用词是当前所在数组)的中间位置元素的大小对比情况决定下一步是在左半部子数列还是右半部子数列进行查找。其实当我们进行到下一步查找,即在某半部子数列进行查找时,我们就把这一过程看做一个独立的过程,这也是为什么我在上面使用“当前数组”这个词的原因,在这一子过程中,当前数组就是前一过程数组的一个子数组。说到这里,我们到该都能嗅到了一丝递归的气息~
很多童鞋在刚接触折半查找时会纠结数组中有几个元素,数组中元素的数量是个位数,例如有七个,数组里面排是0~6,那很容易就知道位于中间位置的元素是3号元素;可是如果数组里有八个元素呢?有些童鞋就会纠结了,八个元素,0~7,怎么也看不出来有中间位置的元素啊,八个元素打对折一边四个严丝合缝啊,中间那还有元素?!写到这里有的同学可能会笑了,不过真的有人问过我这个问题,而且不在少数,我觉得这个问题并不可笑,其实问这些问题的童鞋是掉进了一个思维定式:所谓折半,并非一定要两半元素数量相等啊!我对折半的理解是找出一个相对的位置靠中间元素把原数组划分开,至于分的均匀不均匀就不重要了,因为这种元素个数是偶数数组确实没办法均分。所以,分开就好,不用平均。对于有八个元素的数组,在求中间位置元素的时候我们就(0+7)/2就好了,计算机算出来的会是三,那就以三号元素作为中间位置元素咯,在这里不必纠结~
基本的二分查找C程序实现既可以使用循环,也可以使用递归。相信基本原理都懂,我就直接上代码了。
#include
#include
int mid_num(int low, int high);
int BinarySearchByLoop(int arr[], int len, int dest);
int BinarySearchByRecursion(int arr[], int dest, int low, int high);
int main(int argc, char* argv[])
{
int array[] = {5,12,23,34,87,124,709,1024};
int x = 0;
int i = 0;
int position = 0;
int array_len = sizeof(array)/sizeof(int);
int low = 0;
int high = array_len - 1;
printf("Please input what you want search on this array: \n");
for(i = 0;i < array_len;++i)
{
if(i != (array_len-1))
printf("%d,",array[i]);
else
printf("%d",array[i]);
}
printf("\n");
scanf("%d",&x);
//position = BinarySearchByLoop(array, array_len, x);
position = BinarySearchByRecursion(array, x, low, high);
if(position >= 0)
printf("Your number is in the array and position %d \n",position+1);
else
printf("Sorry, your number is not in the array.\n");
return 0;
}
int mid_num(int low, int high)
{
return int((low + high) / 2);
}
int BinarySearchByLoop(int arr[], int len, int dest)
{
int low = 0;
int high = len - 1;
int mid = mid_num(low, high);
while(low <= high)
{
mid = mid_num(low, high);
if(dest == arr[mid])
return mid;
else if(dest < arr[mid])
high = mid - 1;
else
low = mid + 1;
}
return -1;
}
int BinarySearchByRecursion(int arr[], int dest, int low, int high)
{
int mid = 0;
if(low <= high)
{
mid = mid_num(low, high);
if(dest == arr[mid])
return mid;
else if(dest < arr[mid])
BinarySearchByRecursion(arr, dest, low, (mid - 1));
else if(dest > arr[mid])
BinarySearchByRecursion(arr, dest, (mid + 1),high);
}
else
return -1;
}
int BinarySearchByLoop(int arr[], int len, int dest)
函数是使用循环实现二分查找
int BinarySearchByRecursion(int arr[], int dest, int low, int high)
函数是使用递归实现二分查找
运行结果如下:
如果输入了一个数组中不存在的数:
关于二分查找的初识就这些啦,后面还会有跟深入的学习~