C程序设计--查找(二分法查找/折半查找)

版权声明:本文由 Micheal 博客 创作,转载请附带链接,有问题欢迎交流。 https://blog.csdn.net/qq_42887760/article/details/83934746

二分法查找/折半查找

说明:折半搜索(half-interval search),也称二分搜索(binary search)、对数搜索(logarithmic search),是一种在有序数组中查找某一特定元素的搜索算法。

搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半

  • 优缺点
  1. 优点:是比较次数少,查找速度快,平均性能好;
  2. 缺点:是要求待查表为有序表,且插入删除困难。
    因此,折半查找方法适用于不经常变动而查找频繁的有序列表。
  • 算法步骤描述
    ① 首先确定整个查找区间的中间位置 mid = ( left + right )/2 。
    ② 用待查关键字值与中间位置的关键字值进行比较; 
    若相等,则查找成功 
    若大于,则在后(右)半个区域继续进行折半查找 
    若小于,则在前(左)半个区域继续进行折半查找。
    ③ 对确定的缩小区域再按折半公式,重复上述步骤。最后,得到结果:要么查找成功, 要么查找失败。折半查找的存储结构采用一维数组存放。
  • 代码实现
  1. 主函数:
int main()
{	
	int array[] = {1,2,3,4,5,6,7,8,9};
	int length = sizeof(array)/sizeof(array[0]);//用sizeof()获取数组的长度
	int element;
	scanf("%d",&element);

	int location = binary_research(array,length,element);

	if(location>=0)
		printf("The element's location is %d\n",location);
	else
		printf("Don't exit this element.\n");
	return 0;
} 
  1. 折半查找函数部分:
//在有序表R[0..n-1]中进行二分查找,成功时返回结点的位置,失败时返回-1
int binary_research(int arr[],int length,int element)
{
	int left=0,right=length-1; //置当前查找区间上、下界的初值

	while(left<=right)
	{	
		int mid = (left+right)/2;//会有整数溢出的问题,具体见函数说明

		if(arr[mid]>element)
			right = mid - 1; //继续在R[left..mid-1]中查找
		else if(arr[mid]<element)
			left = mid + 1;	 //继续在R[mid+1..right]中查找
		else 
			return mid;		 //查找成功返回
	}
	return -1;	//当 left>right 时表示所查找区间内没有结果,查找失败
}
关于上述函数说明:
  1. 在第8行代码中:int mid = (left+right)/2;
    使用(left+right)/2会有整数溢出的问题。
    问题会出现在当left+right的结果大于表达式结果类型所能表示的最大值时, 这样,产生溢出后再/2是不会产生正确结果的。
    优化方法:int mid = left + (left - right)/2; //防止越界

因此改进后的程序为:

int binary_research(int array[],int length,int target)
{
    int low=0,high=length-1;
	while(low<=high)
        {
            int mid=low+(high-low)/2;//优化溢出问题
            if(array[mid]>target)
                high=mid-1;
            else if(array[mid]<target)
            low=mid+1;
            else
                return mid;
        }
    return-1;
}

另外一种写法:int binary_research(int arr[],int low,int high,int target);

#include<stdio.h>

int binary_research(int arr[],int low,int high,int target);

int main()
{	
	int array[] = {1,2,3,4,5,6,7,8,9};//数组中的数(由小到大)
	int length = sizeof(array)/sizeof(array[0]);//用sizeof()获取数组的长度
	int low=0,high=length-1;
	int element;
	scanf("%d",&element);

	int location = binary_research(array,low,high,element);

	if(location>=0)
		printf("The element's location is %d\n",location);
	else
		printf("Don't exit this element.\n");
	return 0;
} 

int binary_research(int array[],int low,int high,int target)
{
	while(low<=high)
        {
            int mid=low+(high-low)/2;//优化溢出问题
            if(array[mid]>target)
                high=mid-1;
            else if(array[mid]<target)
            low=mid+1;
            else
                return mid;
        }
    return-1;
}

除此以外还可以使用 递归函数 实现折半查找:

//递归函数实现
int binary_research(int array[],int low,int high,int target)
{
    int mid=low+(high-low)/2;//优化溢出问题
	if(low>high)//查找完毕没有找到答案,返回-1
        return -1;
    else
    {
        if(array[mid]==target)
            return mid;//找到!返回位置.
        else if(array[mid]>target)
            return binary_research(array,low,mid-1,target);//找左边
         else
            return binary_research(array,mid+1,high,target);//找右边
    }
}

参考文章:
1.https://blog.csdn.net/qq_31828515/article/details/51791833
2.https://baike.baidu.com/item/二分查找/10628618?fr=aladdin

猜你喜欢

转载自blog.csdn.net/qq_42887760/article/details/83934746