470 likes | 675 Views
Chapter 9. 搜尋. 9.1 前言. 搜尋 (Search) : 乃是從檔案中尋找出滿足某些特定條件的記錄。 搜尋時須指定: 用哪一個「 鍵 (Key) 」來搜尋。 搜尋的 條件 。 要比較之「 鍵值 」為何。. 9.1 前言. 搜尋的條件判斷種類. 9.1 前言. 4 種主要的搜尋法: 循序搜尋法 (Sequential Searching Method) 。 二分搜尋法 (Binary Searching Method) 。 費氏搜尋法 (Fibonacci Searching) 。
E N D
Chapter 9 搜尋 資料結構導論 - C語言實作
9.1 前言 • 搜尋(Search): 乃是從檔案中尋找出滿足某些特定條件的記錄。 • 搜尋時須指定: • 用哪一個「鍵(Key)」來搜尋。 • 搜尋的條件。 • 要比較之「鍵值」為何。 資料結構導論 - C語言實作
9.1 前言 • 搜尋的條件判斷種類 資料結構導論 - C語言實作
9.1 前言 • 4種主要的搜尋法: • 循序搜尋法(Sequential Searching Method)。 • 二分搜尋法(Binary Searching Method)。 • 費氏搜尋法(Fibonacci Searching)。 • 插補搜尋法(Interpolation Searching)。 資料結構導論 - C語言實作
9.2 循序搜尋法(Sequential Searching Method) • 循序搜尋法又稱為線性搜尋法(Linear Searching Method) 。 • 它從檔案的第一筆紀錄開始到最後一筆記錄,一筆一筆地比較鍵值是否滿足搜尋條件。 • 檔案裡若有n筆紀錄,就須比較n次。 資料結構導論 - C語言實作
9.2 循序搜尋法(Sequential Searching Method) 【例1】循序搜尋(資料未事先經過排序) • 假設有一檔案共計有R0、R1、R2、...、R15等16筆紀錄 • 紀錄之鍵值為:{1,75,387, 88,35,9,789,157,87,91,95,391,472,31,163,391* }。 資料結構導論 - C語言實作
9.2 循序搜尋法(Sequential Searching Method) • 要找出「鍵值等於391」之紀錄 • 共計比較16次 • 結果找出R11及R15共2筆紀錄 資料結構導論 - C語言實作
9.2 循序搜尋法(Sequential Searching Method) • 要找出「鍵值大於等於150」之紀錄 • 共計比較16次 • 找出R2、R6、R7、R11、R12、R14及R15等7筆紀錄 資料結構導論 - C語言實作
9.2 循序搜尋法(Sequential Searching Method) 【例2】循序搜尋(資料已事先經過排序) • 找出「鍵值等於391 」之紀錄 • 只須比較15次 • 結果找出R11及R15共2筆紀錄 資料結構導論 - C語言實作
9.2 循序搜尋法(Sequential Searching Method) • 找出「鍵值大於等於150 」之紀錄 • 只須比較10次 • 找出R7、R14、R2、R11、R15、R12及R6等7筆紀錄 資料結構導論 - C語言實作
9.3 二分搜尋法(Binary Searching Method) • 鍵值必須經過排序 • 比較「第中間筆鍵值」 • 往可能存在滿足搜尋條件的方向去搜尋 • 假設檔案中有編號為0、1、2、...、n-1的n筆紀錄,鍵值依序儲存在陣列d[0]、d[1]、d[2]、d[3]、...、d[n-1]中,並且已經按「鍵值不遞減」之順序排序好了。 資料結構導論 - C語言實作
9.3 二分搜尋法(Binary Searching Method) • 使用二分搜尋法在陣列d中搜尋鍵值K的步驟說明如下: 步驟1:令low=0,high=n-1。 步驟2:當(low <= high)執行步驟3到步驟6, 否則表示找不到,結束。 步驟3:令Ki = 本回合搜尋範圍(d[low]到d[high])中的 「第中間筆」鍵值,即Ki = d[i] = d[(low+high)/2]。 步驟4:若Ki > K則失敗,令high=i-1。 回到步驟2。 步驟5:若Ki < K則失敗,令low=i+1。 回到步驟2。 步驟6:若Ki = K則成功,須繼續比較d[i-1],d[i-2],…, 直到失敗為止,以及繼續比較d[i+1],d[i+2],...,直到失敗為止,結束。 資料結構導論 - C語言實作
9.3 二分搜尋法(Binary Searching Method) 【例1】二分搜尋 • 找出「鍵值K等於391」之紀錄 • 第1回合,Ki=d[i]=d[(0+15)/2]=d[7]=91 • 第2回合,Ki=d[i]=d[(8+15)/2]=d[11]=387 • 第3回合,Ki=d[i]=d[(12+15)/2]=d[13]=391 資料結構導論 - C語言實作
9.3 二分搜尋法(Binary Searching Method) 【例2】二分搜尋 • 找出「鍵值K大於等於150」之紀錄 • 第1回合,Ki=d[i]=d[(0+15)/2]=d[7]=91 • 第2回合,Ki=d[i]=d[(8+15)/2]=d[11]=387 • 第3回合,Ki=d[i]=d[(8+10)/2]=d[9]=157 • 第4回合, Ki=d[(8+8)/2]=d[8]=95 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) • 費氏搜尋法以「費氏數」為比較對象及分割點。 • 費氏數列(Fibonacci Number)Fib是一組整 數:f0、f1、f2、f3、...、fn所成之集合,其 定義如下: f0 = 0, f1 = 1, fn = fn-1 + fn-2,當 n > 1。 • 從0開始的一系列費氏級數:0,1,1,2,3,5,8,13,21,34,55,89, 144,233,377,610,987,... 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) • 包含n個節點且fk = n+1的費氏樹具有下列特徵: • 費氏樹節點編號為1、2、3、...、n。 • 樹根節點之編號為fk-1。 • 左右子樹也都是費氏樹,左子樹根為fk-2,右子樹根為fk-1+fk-3。 • 左子樹共有fk-1 -1個節點,右子樹共有fk-2 -1個節點。 • 費氏樹中每一對兄弟節點與其父親節點之差均相等而其差值亦是一個費氏數。 • 若將節點編號視為鍵值,則費氏樹也是一棵二元搜 尋樹,即某節點的左子樹鍵值都比它小,由右子樹鍵值都大於或等於它。 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) 【例1】費氏樹 • 圖9.1是一棵典型的費氏樹,它共有20個節點,節點編號為:1,2,3,...,20。其特徵如下: 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) • n = fk - 1,20 = fk - 1,fk = 21,所以k = 8。 • 樹根節點之編號為fk-1 = f8-1 = f7 = 13。 資料結構導論 - C語言實作
f(0)、f(1)、f(2)、f(3)、f(4)、f(5)、f(6)、f(7)、f(8) 0 1 1 2 3 5 8 13 21 資料結構導論 - C語言實作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 fk = 21 fk-1 = 13 fk-2 = 8 fk-3 = 5 k=8 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) • 左子樹根為fk-2 = f8-2 = f6 = 8。右子樹根為f8-1+f8-3= f7 + f5 = 13 + 5 = 18。 • 左子樹共有fk-1 – 1 = f7 – 1 = 12個節點,右子樹共有fk-2 – 1 = f6 – 1 = 8 – 1 = 7個節點。 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) 5. 8和18是樹根節點(13)的兩個子節點,且│13-8│=│13-18│= 5,5本身也是一個費氏數。8的兩個子節點分別5和11,│8-5│=│8-11│= 3,3本身也是一個費氏樹。 • 若將節點編號視為鍵值,則該費氏樹也是一棵二元搜尋數。 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) • 假設檔案中有編號為0、1、2、...、n-1的n筆紀錄,鍵值依序儲存在陣列d[0]、d[1]、d[2]、d[3]、...、d[n-1]中,並且已經按「鍵值不遞減」之順序排序好了。 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) • 使用費氏搜尋法在陣列d中搜尋鍵值K的步驟說明如下: 步驟1:找出小於 n+1的最大費氏數fk, 使得fk + m = n+1。 算出fk、k、m之值,其中m >= 0。 步驟2:令樹根i = fk–1。 且令p = fk–2 ,q = fk–3。 步驟3:若K > d[i]則令i = i + m。 步驟4:當(i >= 1)時執行步驟5到步驟7, 否則表示找不到,搜尋結束。 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) 步驟5:若(K < d[i])則{ 若(q == 0)則 i = 0。 否則{ i = i - q。j = p。p = q。q = j - q。} } 回到步驟4。 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) 步驟6:若(K > d[i])則{ 若(p == 1)則 i = 0。 否則{ i = i + q。 p = p - q。 q = q - p。 } } 回到步驟4。 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) 步驟7:若K = d[i]則成功,須繼續比較d[i-1],d[i-2],…,直到失敗為止, 以及繼續比較d[i+1],d[i+2],..., 直到失敗為止,結束。 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) 【例2】費氏搜尋(資料必須先經過排序) • 假設有一檔案共計有R0、R1、R2、...、R15等16筆紀錄,紀錄之鍵值為:{1,9,31,35,75,87,88,91,95,157,163,387,391,391*,472,789},已經按「鍵值不遞減」之順序排序好了,並且依序儲存在陣列d[0]、d[1]、d[2]、d[3]、...、d[15]之中。 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) • 使用費氏搜尋法來找出「鍵值K等於391」之紀錄,其過程如下: 步驟1:找出小於 n+1的最大費氏數fk, 得到f7 = 13,k = 7。又fk + m = n+1,即13 + m = 16 + 1 = 17,m = 4。 步驟2:找出樹根i = fk–1 = f7–1 = f6 = 8。 且p = fk–2 = f5 = 5,q = fk–3 = f4 = 3。 步驟3:比較K與d[i](d[8]),K=391 > d[8]=95, 令i = i + m = 8 + 4 = 12。 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) 步驟4:比較K與d[i](d[12]),K=391 = d[12] = 391,找到了。須再往前比較d[11],結果不符合搜尋條件。然後再往後比較d[13],符合搜尋條件,繼續往後比較d[14],不符合搜尋條件,搜尋結束。 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) 【例3】費氏搜尋(資料必須先經過排序) • 找出「鍵值K等於31」之記錄,其過程如下: 步驟1:找出小於 n+1的最大費氏數fk,得到f7 = 13,k = 7。又fk + m = n+1,即13 + m = 16 + 1 = 17,m = 4。 步驟2:找出樹根i = fk–1 = f7–1 = f6 = 8。 且p = fk–2 = f5 = 5,q = fk–3 = f4 = 3。 步驟3:比較K與d[i](d[8]),K=31 < d[8]=95, 因q不等於0,令i = i – q = 8 – 3 = 5。 令j = p = 5。令p = q = 3。 令q = j – q = 5 – 3 = 2。 資料結構導論 - C語言實作
步驟4:比較K與d[i](d[5]),K=31 < d[5]=87,因q不等於0,令i = i – q = 5 – 2 = 3。令j = p = 3。令p = q = 2。令q = j – q = 3 – 2 = 1。 步驟5:比較K與d[i](d[3]),K=31 < d[3]=35,因q不等於0,令i = i – q = 3 – 1 = 2。令j = p = 2。令p = q = 1。令q = j – q = 2 – 1 = 1。 步驟6:比較K與d[i](d[2]),K=31 = d[2]=31,找到了。 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) 【例4】費氏搜尋(資料必須先經過排序) • 找出「鍵值K等於789」之紀錄,其過程如下: 步驟1:找出小於 n+1的最大費氏數fk,得到f7 = 13,k = 7。又fk + m = n+1,即13 + m = 16 + 1 = 17,m = 4。 步驟2:找出樹根i = fk–1 = f7–1 = f6 = 8。 且p = fk–2 = f5 = 5,q = fk–3 = f4 = 3。 步驟3:比較K與d[i](d[8]),K=789 > d[8]=95, 令i = i + m = 8 + 4 = 12。 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) 步驟4:比較K與d[i](d[12]),K=789 > d[12]=391,因p不等於1,令i = i + q = 12 + 3 = 15。令p = p – q = 5 – 3 = 2。令q = q – p = 3 – 2 = 1。 步驟5:比較K與d[i](d[15]),K=789 = d[15]=789,找到了。 資料結構導論 - C語言實作
9.4 費氏搜尋法(Fibonacci Searching) 資料結構導論 - C語言實作
9.5 插補搜尋法(Interpolation Searching) • 假設鍵值已經按「不遞減」之順序排序並儲存在陣列d[low]、d[low+1]、...、d[high]之中 • 插補搜尋法是拿d[i]來與要搜尋之鍵值K做比較,其中 資料結構導論 - C語言實作
9.5 插補搜尋法(Interpolation Searching) • 假設鍵值已經按「不遞減」之順序排序假設檔案中有編號為0、1、2、...、n-1的n筆記錄,鍵值依序儲存在陣列d[0]、d[1]、d[2]、d[3]、...、d[n-1]中,並且已經按「鍵值不遞減」之順序排序好了。 資料結構導論 - C語言實作
9.5 插補搜尋法(Interpolation Searching) • 使用插補搜尋法在陣列d中搜尋鍵值K的步驟說明如下: 步驟1:令low = 0,high = n-1。 步驟2:當(low <= high)時執行步驟 3 到 步驟 6,否則表示找不到,搜尋結束。 步驟3:令 步驟4:若(K < d[i]且high != i-1)則 令 high = i – 1。回到步驟2。 資料結構導論 - C語言實作
9.5 插補搜尋法(Interpolation Searching) 步驟5:若(K > d[i]且low != i+1)則 令low = i + 1。回到步驟2。 步驟6:若K = d[i]則成功,須繼續比較d[i-1],d[i-2],…,直到失敗為止,以及 繼續比較d[i+1],d[i+2],...,直到 失敗為止。搜尋結束。 資料結構導論 - C語言實作
9.5 插補搜尋法(Interpolation Searching) 【例1】插補搜尋(資料必須先經過排序) • 假設有一檔案共計有R0、R1、R2、...、R15等16筆紀錄,紀錄之鍵值為:{1,9,31,35,75,87,88,91,95,157,163,387,391,391*,472,789},已經按「鍵值不遞減」之順序排序好了,並且依序儲存在陣列d[0]、d[1]、d[2]、d[3]、...、d[15]之中。 資料結構導論 - C語言實作
9.5 插補搜尋法(Interpolation Searching) • 使用插補搜尋法來找出「鍵值K等於391」之紀錄,其過程如下: 步驟1:令low = 0,high = n-1 = 15。 步驟2:i = low+(391-d[low])/(d[high]-d[low])*(high-low) = 0+(391-d[0])/(d[15]-d[0])*(15-0) = 0+(391-1)/(789-1)*(15-0) = 0+390/788*15 = 7。 資料結構導論 - C語言實作
9.5 插補搜尋法(Interpolation Searching) 步驟3:比較K與d[i](d[7]),K=391 > d[7]=91,令low = i+1=7+1 = 8。 步驟4:i = low+(391-d[8])/(d[15]-d[8])*(15-8) = 8+(391-95)/(789-95)*(15-8) = 8+296/694*7 = 10。 資料結構導論 - C語言實作
9.5 插補搜尋法(Interpolation Searching) 步驟5:比較K與d[i](d[10]),K=391 > d[10]=163,令low = i+1 = 10+1 = 11。 步驟6:i = low+(391-d[11])/(d[15]-d[11])*(15-11) = 11+(391-387)/(789-387)*(15-11) = 11+4/402*4 = 11。 資料結構導論 - C語言實作
9.5 插補搜尋法(Interpolation Searching) 步驟7:比較K與d[i](d[11]),K=391 > d[11]=387,令low = i+1 = 11+1 = 12。 步驟8:i = low+(391-d[12])/(d[15]-d[12])*(15-12) = 12+(391-391)/(789-391)*(15-12) = 12+0/398*3 = 12。 步驟9:比較K與d[i](d[12]),K=391 = d[12] = 391,找到符合條件的資料了。 資料結構導論 - C語言實作
9.6 搜尋法的效益分析比較 資料結構導論 - C語言實作