• python算法之二分查找


    说明:大部分代码是在网上找到的,好几个代码思路总结出来的

    通常写算法,习惯用C语言写,显得思路清晰。可是假设一旦把思路确定下来,并且又不想打草稿。想高速写下来看看效果,还是python写的比較快。也看个人爱好。实习的时候有个同事对于python的缩进来控制代码块各种喷。。。。他认为还是用大括号合适。。。怎么说呢,适合自己的才是最好的。我个人的毛病就是,写了几天C,到要转到python的时候,代码中依旧有C的影子。。比方大括号问题,比方忘记在while或这for、if、else等后面加“:”。而假设写了几天Python,要转到C的时候。会忘记声明一些变量。直接拿来就用。执行的时候,各种变量没有定义。在这里给自己提个醒。多思考也要多动手。

    今天无意中看到了二分查找。本来以为非常easy的代码。几行就结束了,后来看到了一个比較牛的代码。才发现人比人该死是永恒的真理。为了不该死,也要把不该死的代码学会才行啊,二分查找的原理非常easy,就是在一个有序序列中。查找代码是一半一半的比較而不是一个一个的比較

    最简单的二分查找非递归代码例如以下:

    int search(int array[], int n, int v)
    {
        int left, right, middle;
    
        left = 0, right = n - 1;
    
        while (left <= right)
        {
            middle = (left + right) / 2;
            if (array[middle] > v)
            {
                right = middle;
            }
            else if (array[middle] < v)
            {
                left = middle;
            }
            else
            {
                return middle;
            }
        }
    
        return -1;
    }

    输入:array数组。array大小n,查找元素v

    输出:v的所在位置,没有找到返回-1

    #####################################################################################################################################

    以下写个递归的代码:

    #include<stdio.h>
    
    int search(int arr[],int low,int high,int key)
    {
            int mid = (low+high)/2;
            if(low > high)
                    return -1;
            if(arr[mid] == key)
                    return mid;
            else if(arr[mid]>key)
                    return search(arr,low,mid-1,key);
            else
                    return search(arr,mid+1,high,key);
    }
    int main()
    {
            int arr[101] = {1,2,3,4,87,90,100};
            int low = 0,high = 8,key = 87,ret;
            ret = search(arr,low,high,key);
            if(ret != -1)
                    printf("the return is %d",ret);
            else
                    printf("FBI warning:the return is -1,not find the key");
    }

    不知道递归的同学。请參考递归的吐槽。。。如图:当年第一次听到老师说递归的时候,想的就是这个


    可是事实上递归是这种


    好了不扯了。二分查找这个代码事实上细致看的话还是有点问题的。比方说这个三次推断。两次比較。还有就是

    在循环体内,计算中间位置的时候,使用的是这个表达式:

    mid = (left + right) / 2;

    假如,left与right之和超过了所在类型的表示范围的话,那么middle就不会得到正确的值.
    所以,更稳妥的做法应该是这种:
    mid = left + (right - left) / 2;
    那我们优化一下,python代码例如以下:

    def search(arr,n,v):
            left = -1
            right = n
            while(left+1 != right):
                    mid = left+(right-left)/2
                    if(arr[mid] < v):
                            left = mid
                    else:
                            right = mid
            if(right >= n or arr[right] != v):
                    right = -1
            return right
    if __name__ == '__main__':
            arr = [1,2,4,23,87,90,555,1222,1444]
            n = len(arr)
            ret = search(arr,n,87)
            print ret
    

    看C的代码:

    int search(int array[], int n, int v)
    {
        int left, right, mid;
    
        left = -1, right = n;
    
        while (left + 1 != right)
        {
            mid = left + (right - left) / 2;
    
            if (array[mid] < v)
            {
                left = mid;
            }
            else
            {
                right = mid;
            }
        }
    
        if (right >= n || array[right] != v)
        {
            right = -1;
        }
    
        return right;
    }
    


    这个代码先不说理不理解,光返回值仅仅用right这个就非常牛逼,这样看着非常easy,可是非常精髓的感觉有没有?再看while的推断,left+1!=right是不是非常正点?自己理解ba



  • 相关阅读:
    EPANET头文件解读系列4——EPANET2.H
    EPANET头文件解读系列3——TOOLKIT.H
    EPANET头文件解读系列2——ENUMSTXT.H
    EPANET头文件解读系列1——TEXT.H
    ENUMSTXT.H中的指针数组
    main函数的参数
    函数指针与指针函数
    FMDB源码阅读
    17个提升iOS开发效率的必用工具
    UIKit性能调优实战讲解
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5185668.html
Copyright © 2020-2023  润新知