二分查找算法及分析

二分查找
一般而言,对于包含n个元素的列表,用二分查找最多需要log2n步,而简单查找最多需要n步。

其实如果有m个元素
    找出一个数n
        使得m除以2的n次方小于等于1
            那么需要判断的次数就是n+1
算法实现一
    得数组长度length
        判断num与数组的length/2的大小
            如果大于length/2
                判断length/2 + length/4 大小
                    。。。
            如果小于length/2 
                判断length/2 - length/4 大小
                    。。。
    太麻烦,而且不可行,如果需要比较n次,那么就得有2^(n-1)个if else 语句 【二叉树的形态】
算法实现二
    使用递归,使用两个位置指针low,high,low代表最低索引,high代表最高索引
        每次要测试的数test只是跟low和high 的中间值比较
            如果大于中间值
                low就变大,变为这个中间值
            如果小于中间值
                High就变小,变为这个中间值
            每次只要根据变化后的low和high 计算出中间值,在跟test比较即可
            而且每次都是相同的过程,可以使用递归,再次调用这个函数本身,
            (其实这个函数的作用主要是获得下一个要与test比较的中间值并与其比较)
    ///**********************************************
    ///*************二分查找算法(2)
    ///使用递归的方式
    ///需要输入的参数有 数组,要判断的数值,一开始计算出的数组中间位置的下标,数组起始位置(一般为0),数组的长度
    ///每次变化的是与要测试数值比较的中间位置的下标num
    ///num根据与测试数值比较的情况进行改变,是变大还是变小
    ///返回:与test相等的数组元素的下标
    ///作用:判断一个数是否存在于数组中
    ///递归次数: 不多于n+1次(n为使用二分查找时比较的次数)
    ///**********************************************

    int binary(int b[],int test,int num,int low,int high)
    {
        t_num++;
        if(test>b[num])
        {
            low = num;
            num = (low+high)/2;
            if(num==high-1)      ///防止测试数字不在数组中而无限递归,防止大于最大
            {
                return -1;
            }
            binary(b,test,num,low,high);
        }
        else if(test<b[num])
        {
            high = num;
            num = (low+high)/2;
            if(low == high)   ///防止测试数字不在数组中而无限递归,防止小于最小
            {
                return -1;
            }
            binary(b,test,num,low,high);

        }
        else if(test == b[num])
        {
            return num;
        }
    }
算法实现3
    使用循环,不用递归,依旧可以实现要测试 的数据只与中间值比较,只不过是使用循环不断刷新中间值
    ///**********************************************
    ///*************二分查找算法(3)
    int binary_p(int e[],int length,int item)
    {
        int low = 0;
        int mid;
        int high = length-1;
        while(low<=high)
        {
            p_num++;
            mid = (low+high)/2;
            if(item == e[mid])
            {
                return mid;
            }
            if(item > e[mid])
            {
                low = mid+1;
            }
            else
            {
                high = mid-1;
            }

        }
        return -2;
    }


两种算法比较:
        如果要查找的数是第一个,算法2比算法3多比较一次
        如果要查找的数是最后一个,算法3要多查找一次
        如果要查找的数位于中间,两个算法查找的次数是相同的

对于数组或者链表这样的线性结构,如果涉及到其中元素的位置,可以设置几个位置指针用来在这个线性结构上来回查看,可以实现双向的查找,效率更高,也可以做更多事情,更灵活。
完整代码
    #include <iostream>
    using namespace std;
    int t_num =0;///测试算法2的比较次数
    int p_num =0;///测试算法3的比较次数
    ///**********************************************
    ///*************二分查找算法(2)
    ///使用递归的方式
    ///需要输入的参数有 数组,要判断的数值,一开始计算出的数组中间位置的下标,数组起始位置(一般为0),数组的长度
    ///每次变化的是与要测试数值比较的中间位置的下标num
    ///num根据与测试数值比较的情况进行改变,是变大还是变小
    ///返回:与test相等的数组元素的下标
    ///作用:判断一个数是否存在于数组中
    ///递归次数: 不多于n+1次(n为使用二分查找时比较的次数)
    ///**********************************************

    int binary(int b[],int test,int num,int low,int high)
    {
        t_num++;
        if(test>b[num])
        {
            low = num;
            num = (low+high)/2;
            if(num==high-1)      ///防止测试数字不在数组中而无限递归,防止大于最大
            {
                return -1;
            }
            binary(b,test,num,low,high);
        }
        else if(test<b[num])
        {
            high = num;
            num = (low+high)/2;
            if(low == high)   ///防止测试数字不在数组中而无限递归,防止小于最小
            {
                return -1;
            }
            binary(b,test,num,low,high);

        }
        else if(test == b[num])
        {
            return num;
        }
    }
    ///**********************************************
    ///*************二分查找算法(3)
    int binary_p(int e[],int length,int item)
    {
        int low = 0;
        int mid;
        int high = length-1;
        while(low<=high)
        {
            p_num++;
            mid = (low+high)/2;
            if(item == e[mid])
            {
                return mid;
            }
            if(item > e[mid])
            {
                low = mid+1;
            }
            else
            {
                high = mid-1;
            }

        }
        return -2;
    }
    void test_02(int tu)///用来测试算法3
    {
        int c[90];
        int kk;
        for(int i =0;i<90;i++)
        {
            kk=i+5;
            c[i]=kk;
        }
        for(int j=0;j<90;j++)
        {
            cout<<c[j]<<" ";
        }
        int length = sizeof(c)/sizeof(c[0]);
        int ll = binary_p(c,length,tu);
        if(ll!=-2)
        {
               cout<<ll<<endl;

        }
        else{
            cout<<"nnnnnnn"<<endl;
        }
        cout<<p_num<<"p_num************"<<endl;

    }
    int main()
    {
        int tt;
        cin>>tt;
        int a[128];
        int kk;
        for(int i =0;i<128;i++)
        {
            kk=i+5;
            a[i]=kk;
        }
        for(int j=0;j<128;j++)
        {
            cout<<a[j]<<" ";
        }
        cout<<endl;
        int low1 =0;
        int high1 = sizeof(a)/sizeof(a[0]);
        int num1 = (low1+high1)/2;
        int number = binary(a,tt,num1,low1,high1);
        if(number !=-1)
        {
            cout<<number<<endl;

        }
        else
        {
            cout<<"no this number"<<endl;
        }
        cout<<"hello c++";
        cout<<endl;
        cout<<t_num<<"t_num**********"<<endl;
        test_02(tt);
        return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值