在一個列表當中我們可以進行線性查找也可以進行二分查找,即通過不同的方法找到我們想要的數字,線性查找即按照數字從列表里一個一個從左向右查找,找到之后程序停下。而二分查找的效率往往會比線性查找更高。
一.二分查找的步驟
二分查找的步驟首先是將列表進行升序或者降序排列,否則無法進行數字的比較,也就無法進行二分查找。然后找到一個列表的中間數值(mid),如果列表當中的數字和為基數,則為最中間的那個數。如果為偶數,則為最中間的那兩個數的左邊那一個,比如說我們有一個列表,[1,2,3,4,5,6],列表當中的數字為偶數個,那么mid則是3。找到mid之后,再和我們需要查找的數字進行比較,如果比我們需要查找的數字要小,那么就讓low=mid+1,即在Mid的右邊一個,如果比我們需要的數字要大,則讓high=mid—1,在high的左邊一個,利用夾逼法直到mid等於var的時候這個時候在返回mid的值,這個值就是我們數字所在的順序數,在列表當中的order或稱index(索引)。我們下面一張圖來表示二分查找的步驟,下面是舉了一個最為簡單的列子,數字的個數僅為4個,且為1,2,3,4。
假設我們想要找的數字為3的index,因此首先在第一次循環當中,1=low,4=high,mid=2,我們令var=3,也就是我們想要找的數為var,發現這個數的數值是比mid的數值更大的,因此low=mid+1,此時mid所代表的數值變成了3。緊接着我們進行下一次循環,我們發現var和mid是相等的,因此返回mid的數值(並非mid所對應在列表當中的數值,而是mid自己的值),這樣就可以得到var的索引值了!實現的程序如下:
# 首先咱們來看一個線性查找,這個的效率比較低 li = [1,2,3,4,0,4,2,3] # print(6 in li)# 這個就是線性查找,看6是否在里面 # print(li.index(6))# 看6在第幾個index li.sort() print("進行排序之后的列表為:{}".format(li)) def bin_search(li, var): low = 0 high = len(li) - 1 while low<=high:# 這里不能夠使用while true!!不然輸入一個不存在的值的話就會導致mid做了加減法后low比high大或者high比Low小,失去了比較的意義 mid = (low + high) // 2 if li[mid] == var: return mid elif li[mid] < var: low = mid + 1 else:# li[mid] > var high = mid - 1 return -1 # 二分查找的時間復雜度為log(n) if __name__ == "__main__": print(bin_search(li, 3))
在程序當中需要注意的是循環while的判斷條件是low<=high,因為如果在輸入的值var不屬於列表的情況下,運算到最后low就會大於high,這種情況下是應該直接返回-1的,而不是繼續運算到無窮無盡。在這個程序當中我們設定了列表li,並通過定義二分查找函數來執行二分查找的過程。程序也很通俗易懂,和之前我們講過的二分查找的步驟是一樣的,下面我們來看一個利用二分查找的例題:
二.例題
這個例題節選自悉尼大學“Python編程”這門課的每周同步編程練習,題目是這樣的:
輸入一個序列,然后讓整個序列變成一個有序的列表,最后找到數字8在這個列表當中的位置,我們可以使用二分查找來做這道題目,標准的Example如下:
現在我們使用二分查找算法來實現這個問題,首先是輸入的字符串用input()函數來進行接收,但是接收之后的數字是字符串,我們需要使用split()函數將其每一個元素通過間隔開,由於使用了split()函數,因此就會自己動返回一個列表,不過里面每一個數字也還是string型,我們再利用一個for循環將其改變為int型,再重新灌入一個列表當中,形成interger型的列表,也就是我們第二個的輸出結果,最后運用咱們剛才的二分查找法,得到數字8的index值,程序如下:
def binary_search(list, var): low = 0 high = len(list)-1 while low <= high: mid = (low+high)//2 if list[mid] == var: return mid elif list[mid] < var: low=mid+1 else: high=mid-1 return -1 a = input("Enter some integers:") a = a.split(",") print(a) ls = [] for i in a: b = int(i) ls.append(b) print("我們得到的數組是:{}".format(ls)) # 將列表進行升序排列,這樣才可以使用二分查找算法 ls.sort() print(ls) if __name__ == "__main__": print(binary_search(ls,5))
輸出結果如下:
E:\conda\python.exe F:/computer/datast/T4Q6P4.py Enter some integers:23,4456,234,67,5 ['23', '4456', '234', '67', '5'] 我們得到的數組是:[23, 4456, 234, 67, 5] [5, 23, 67, 234, 4456] 0
今天的教程就到這里了!希望你看了之后會有收獲!