Search
搜尋法
搜尋(Search)
搜尋就是在一堆資料中找出所要之特定資料。搜尋之主要核心動作為「比較」動作,必需透過比較才有辦法判斷是否尋找到特定資料。當資料量少時很容易,當資料量龐大時,如何快速搜尋為一重要課題。
一般電腦檔案都是一群結構記錄之集合(如上一單元之成績結構)。為了排序與搜尋,至少會設定其中一個欄位為資料之鍵值(key)。透過鍵值將資料排列順序,稱為排序。透過鍵值找到特定資料,稱為搜尋(search)。一般資料搜尋有下列分類:
依資料量大小
1. 內部搜尋:欲搜尋之資料較少,可直接載入記憶體中,進行搜尋動作。
2. 外部搜尋:欲搜尋之資料較多,無法一次載入記憶體進行搜尋動作。需使用外部輔助記憶體分批處理。
依搜尋時資料表格是否異動
1. 靜態搜尋:搜尋過程中,資料表格不會有任何異動(如:新增、刪除或更新)。例如:查閱紙本字典、電話簿。
2. 動態搜尋:搜尋過程中,資料表格會經常異動。
一般搜尋常見之演算法有,「循序搜尋」、「二分搜尋」、「二元樹搜尋」、「雜湊搜尋」。
循序搜尋法(Sequential Search)
【定義】 從第一個資料開始取出,依序一一與「目標資料」相互比較,直到找到所要元素或所有資料均尋找完為止,此方法稱「循序搜尋」。
【優點】(1) 程式容易撰寫。
(2) 資料不須事先排序(Sorting)。
【缺點】 搜尋效率比較差(平均次數=(N+1)/2),不管是否有排序,每次都必須要從頭到尾找一次。
【時間複雜度】
(1) 如果資料沒有重覆,找到資料就可終止,否則要找到資料結束。N筆資料,在最差之情況下,需作N次比較,O(N)。
(2) 在平均狀況下(假設資料出現與分佈之機率相等)需(N+1)/2次比較,所以平均時間與最差時間為O(N),最好為O(1)=1次。
【演算法】
int sequential_search(int list[], int n, int key)
{
int i;
for (i = 0; i < n; i++)
{
if (list[i] == key) return i+1;
//比對陣列內的資料是否等於欲搜尋的條件
//若找到符合條件的資料,就傳回其索引
}
return(-1);
//若找不到符合條件的資料,就傳回 -1
}
二分搜尋法(Binary Search)
【定義】如果資料已先排序過,則可使用二分法來進行搜尋。二分法是將資料分成兩部份,再將鍵值與中間值比較,如鍵值相等則找到,小於再比前半段,大於再比後半段。如此,分段比較至找到或無資料為止。
【優點】搜尋效率佳(平均次數=Log2N)。
【缺點】 (1) 資料必需事先排序。
(2) 檔案資料必需使是可直接存取或隨機檔。
【時間複雜度】因為每次比較都會比上一次少一半之資料,因此最多只需要比較 ,。
【演算法】
Searchtime = 0; //搜尋次數初值設定為
Middle = (int)((Low + High)/2); //搜尋中間值
do
{
Searchtime = Searchtime + 1;
if (Temp[Middle] == Key) //找到資料
{
printf("該數字是排在第 %d 個順位",Middle);
//顯示資料位置
printf("一共搜尋 %d 次",Searchtime);
//顯示搜尋次數
break; //跳出迴圈
}
else if(Temp[Middle] < Key)
Low = Middle + 1; //改變左半部
else High = Middle - 1; //改變右半部
Middle = (int)((Low + High) / 2); //改變中間值
}
while(Low <= High);
二元樹搜尋法(Tree Search)
【定義】二元數是先將資料列建立為一棵二元搜尋樹,樹中每節點皆不小於左子樹(葉),也不大於右子樹(葉),也就是 左子樹的值≦樹根值≦右子樹的值。
【優點】 (1) 插入與刪除時,只需改變指標。
(2) 二元樹效率較高(介於循序法與二分法間)。
【缺點】 (1) 有左、右兩指標,需較大記憶體空間。
(2) 資料必須事先排序。
【時間複雜度】平均與最差時間為O(N)
內插搜尋法(Interpolation Search)
【定義】內插搜尋法是二分搜尋法之改良版。是依照資料位置分佈,運用公式預測資料所在位置,再以二分法方式逼近。內插之預測公式為:
【優點】資料分佈平均時,搜尋速度極快。
【缺點】 (1) 需計算預測公式。
(2) 資料必須事先排序。
【時間複雜度】取決於資料分部情形,平均而言優於Log2N。
【演算法】
int intsrch(int A[], int find)
{
int low, mid, high,Searchtime;
low = 0;
high = MAX - 1;
Searchtime = 0; //搜尋次數初值設定為
while(low <= high)
{
mid = (high-low)* (find-A[low])/(A[high]-A[low])+ low;
Searchtime = Searchtime + 1;
if(mid < low || mid > high) return -1;
if(find < A[mid]) high = mid - 1;
else if(find > A[mid])
low = mid + 1;
else
{
printf("一共搜尋 %d 次, ",Searchtime);//顯示搜尋次數
return mid;
}
}
return -1;
}
雜湊搜尋法(Hashing Search)
存取資料時,並不依資料順序存取,是應用資料中某欄位之值代入事先設計好之函數(雜湊函數),計算資料存放之位置。這種方式稱雜湊法(Hashing)。
【定義】將資料按照某特定法則轉換為資料儲存位置,應用時是以資料鍵值(key value)轉換。
【優點】 (1) 搜尋速度最快。
(2) 資料不須是先排序。
(3) 在沒發生碰撞(collision)與溢位(overflow)之情況下,只需一次即可讀取。
(4) 搜尋速度與資料量大小無關。
(5) 保密性高,若不知雜湊函術,無法取得資料。
【缺點】 (1) 浪費空間(因有溢位資料區),並且儲存空間的利用率比循序檔差。
(2) 有碰撞問題,當資料檔記錄到一定量時會嚴重影響處理速度存取速度。
(3) 程式設計比較複雜。
(4) 大量資料無效率。
(5) 不適合循序型煤體,如磁帶。
【演算法】主要依雜湊函數之計算、碰撞與溢位為考量依據。以下簡單討論幾種雜湊函數與溢位處理方法。