二分(折半)查找

折半查找:又叫二分查找,采用分治思想,适用于不经常变动且查找频繁的表;


算法思想:

将n个元素(假设n个元素升序)分为大致相同的两部分,取data[n / 2] 与目标元素m比较:

若data[n/2] == m:return (n / 2);

若data[n/2] > m:则我们只要在data[]的左半部分继续查找;

若data[n/2] < m:则我们只要在data[]的有半部分继续查找;

时间复杂度:O(logn)


优点:比较次数少,查找速度快,平均性能好;

缺点:要求待查表为"有序表",且插入删除困难;


边界错误问题:

(1)左闭右开区间([left , right))。

left = 0 , right = length;

循环条件while(left < right):

data[middle] > m:right = middle;

data[middle] < m: left = middle + 1;


(2)左右皆闭区间([left , right])。

left = 0 , right = length - 1;

循环条件while(left <= right):

data[middle] > m:right = middle - 1;

data[middle] < m:left = middle + 1;

循环体外的初始化条件与循环体内的初始化条件,在迭代时必须一致的区间规则;



代码实现:

#include<iostream>
#include<exception>
using  namespace std;
//---------------------------------------------二分查找(顺序查找)---------------------------------------
int BinSearch_Soulation1(const int* data , int length , int m)
{
	//左闭右闭区间
	int left = 0;
	int right = length - 1 ;

	while(left <= right)
	{
		//middle = (right + left) / 2 不可取;
		//若(right + left) 溢出时,出现错误;
		int middle = left + (right - left) / 2;

		if(data[middle] > m)
		{
			right = middle - 1;
		}
		else if(data[middle] < m) 
		{
			left = middle + 1;
		}
		else
		{
			return middle;
		}
	}

	return -1;
}


int BinSearch_Soulation2(const int* data , int length , int m)
{
	//左闭右开区间
	int left = 0;
	int right = length;
	int middle;

	while(left < right)
	{
	      middle = left + ((right - left) / 2);

		if(data[middle] > m)
		{
			right = middle;
		}
		else if(data[middle] < m)
		{
			left = middle + 1;
		}
		else
		{
			return middle;
		}
	}

	return -1;
}

int BinSearch_Soulation3(const int* data, int length, int m)
{
    int left, right, middle;

    left = -1, right = length;

    while (left + 1 != right)//这个循环维持的条件是left<right && array[left]<v<=array[right],所以到最后的时候,
    {//如果可以找到目标,则只剩下两个数,并且满足 array[left]<v<=array[right],是要查找的数是right
        middle = left + (right - left) / 2;

        if (data[middle] < m)//必须保证array[left]<v<=array[right],所以left = middle;
        {//如果left =middle+1,则有可能出现 array[left]<=v的情况
            left = middle;
        }
        else
        {
            right = middle;
        }
    }

    if (right >= length || data[right] != m)
    {
        right = -1;
    }

    return right;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值