1. 程式人生 > >資料結構與演算法之兩種查詢方法

資料結構與演算法之兩種查詢方法

本節的內容:

  1. 什麼是列表查詢;

  2. 順序查詢(線性查詢);

  3. 二分查詢;

  4. 順序查詢與二分查詢比較;

  5. 執行時間;

  6. 增速問題

一:什麼是查詢

查詢:在一些資料元素中,通過一定的方法找出與給定的關鍵詞相同的資料元素的過程。

二:順序查詢(線性查詢):從列表中查詢指定的元素

定義:從列表的第一個元素開始,順序進行搜尋,直到找到元素或搜尋到列表最後一個元素為止。

  • 輸入:列表、帶查詢的元素

  • 輸出:元素下標(未找到元素是一般返回None/-1)

  • 內建列表查詢函式:index()

 1 #線性查詢的程式碼實現
 2 #enumerate() 函式用於將一個可遍歷的資料物件(如列表、元組或字串)組合為一個索引序列,同時列出資料和資料下標,一般用在 for 迴圈當中。
 3 #教程:https://www.runoob.com/python3/python3-func-enumerate.html
 4 def linear_search(li,var):
 5     for index,v enumerate(li):
 6         if v == var:
 7             return index
 8     else:
 9         return None
10 複雜度:範圍是列表(n),一個for迴圈====》O(n) 從頭到尾遍歷每個元素

 

三:二分查詢定義

又叫折半查詢,從有序列表(必須為有序)的初始候選區list[o:n]開始,通過對待查詢的值與候選區中間值的比較,可以使候選區減少一半。(僅當列表為有序的時候,二分查詢才管用)

舉例:從下面列表中查詢3元素:

首先我們需要對候選區做一個瞭解,這樣有助於我們更好的理解,

在上面的列表中我們使1所在的位置為left,9所在的位置為right,這樣從left-right就是候選區,

候選區中間值(mid) =(left-right)// 2;如果我們需要查詢的值(val)大於候選區中間值(mid),則左邊的值為:left = mid+1 ,right不變,候選區為:【(mid+1),right】;相反:查詢的值(val)小於候選區中間值(mid),則left不變,右邊值為:right = mid - 1,候選區為【left, ( mid -1)】

然後依次進行取值,其中left、mid、right都是指的值的下標;如果最後left>right,則表示該範圍沒有所需要的值。

程式碼如下:

 1 def Binary_search(li,val): #li傳入的列表,val所需要的值
 2     '''定義值'''
 3     left = 0
 4     right = len(li) - 1
 5     while left <= right: #候選區有值
 6         mid = (right+left) // 2  #候選區中間值
 7         if li[mid] == val:
 8             return mid
 9         elif li[mid] > val: #帶查詢的值在中間值(mid)的左側
10             right = mid -1
11         else:  #li[mid] < val 帶查詢的值在中間值(mid)的右側
12             left = mid + 1
13     else:
14         return None

四:順序查詢與二分查詢比較

我們在使用大O表示法討論執行時間時,log指的都是log2。使用簡單查詢法查 找元素時,在最糟情況下需要檢視每個元素。

因此,如果列表包含8個數字,你最多需要檢查8 個數字。而使用二分查詢時,最多需要檢查log n個元素。如果列表包含8個元素,你最多需要 檢查3個元素,因為log 8 = 3(2^3 = 8)。如果列表包含1024個元素,你最多需要檢查10個元素, 因為log 1024 = 10(2^10 =1024)。

五:兩者執行時間

選擇演算法的時候我們本能的選擇效率最高的,以最大限度的減少執行時間或者佔用空間。

如果列表包含100個數字,順序查詢最多需要猜100次,40億個數字,則最多需要才40億次;順序查詢最多需要猜測的次數與列表長度相同==》執行時間線性時間。

二分查詢的話最多猜7次,40億最多猜32(log2^32)次===>執行時間表示為對數時間。

六:增速問題 (演算法的執行時間以不同的速度增加 )

隨著元素數量的增加,二分查詢需要的額外時間並不多, 而順序查詢需要的額外時間卻很多。因此,隨著列表的增長,二分查詢的速度比順序查詢快得多,但如果是無序列表,使用二分查詢的話需要進行排序,兩者各有優缺點,