python算法之二分查找

說明:大部分代碼是在網上找到的,好幾個代碼思路總結出來的

通常寫算法,習慣用C語言寫,顯得思路清晰,但是如果一旦把思路確定下來,而且又不想打草稿,想快速寫下來看看效果,還是python寫的比較快,也看個人愛好,實習的時候有個同事對於python的縮進來控制代碼塊各種噴。。。。他覺得還是用大括號合適。。。怎麼說呢,適合自己的纔是最好的。我個人的毛病就是,寫了幾天C,到要轉到python的時候,代碼中依然有C的影子。。比如大括號問題,比如忘記在while或這for、if、else等後面加“:”,而如果寫了幾天Python,要轉到C的時候,會忘記聲明一些變量,直接拿來就用,運行的時候,各種變量未定義。在這裏給自己提個醒,多思考也要多動手。

今天無意中看到了二分查找,本來以爲很簡單的代碼,幾行就結束了,後來看到了一個比較牛的代碼,才發現人比人該死是永恆的真理,爲了不該死,也要把不該死的代碼學會才行啊,二分查找的原理很簡單,就是在一個有序序列中,查找代碼是一半一半的比較而不是一個一個的比較

最簡單的二分查找非遞歸代碼如下:

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這個就很牛逼,這樣看着很簡單,但是很精髓的感覺有沒有?再看while的判斷,left+1!=right是不是很正點?自己理解ba



發佈了23 篇原創文章 · 獲贊 9 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章