搜尋(Search)

搜尋(Search) 1

依資料量大小... 1

依搜尋時資料表格是否異動... 1

循序搜尋法(Sequential Search) 2

二分搜尋法(Binary Search) 2

二元樹搜尋法(Tree Search) 2

內插搜尋法(Interpolation Search) 3

雜湊搜尋法(Hashing Search) 3

雜湊函數... 3

中間平方法(mid-square) 4

折疊法(folding) 4

除法(Division) 4

數字分析法(digital analysis) 5

解決溢位(overflow handling) 5

線性探測法(linear probing) 5

鏈結串列(chaining) 5

平方探測(quadratic probing) 5

再雜湊(rehashing)... 5

 

搜尋(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) 不適合循序型煤體,如磁帶。

【演算法】主要依雜湊函數之計算、碰撞與溢位為考量依據。以下簡單討論幾種雜湊函數與溢位處理方法。

雜湊函數

雜湊函數之相關名詞說明:

【桶,bucket】雜湊表中儲存資料的位置,每一位置給定一個唯一的位址,此位址稱為bucket address

【槽,slot】每一個位置()有多個資料儲存區,每一儲存區稱為槽(slot)。每一槽可以容納一筆記錄。

【碰撞,collision】當不同之鍵值經雜湊函數計算後,落在相同的位置(bucket address),稱之為碰撞。

【溢位,overflow】如有一鍵值經雜湊函數計算後,相對應之位置(,bucket)已裝滿,就稱為溢位。

中間平方法(mid-square)

此方法,鍵值平方後,取出中間某些位元當作資料儲存的位址。

【範例】假設有一鍵值k=510324。若儲存空間(桶數目)104,也就是取四位數(0000~9999)。則雜湊函數h(k)

h(k)=k2取中間四位數=260430584976取中間四位數=3058

折疊法(folding)

此方法,是將鍵值分為數段,除最後一段外,其餘各段皆等長(等於儲存空間,桶數目)。然後,將各段相加,就可得所對應之位址。相加方式有兩種:

【位移折疊,shifting folding】將各段直接相加。

範例:鍵值123203241112205

à123,203,241,112,205à(+)à884 (hash address)

【邊界折疊,folding at the boundaries】將奇數段或偶數段反轉後相加。

範例:鍵值123203241112205

à123,203,241,112,205à(偶反轉)

à123,302,241,211,205à1082(hash address)

除法(Division)

此方法運用MOD運算,將鍵值X除以某一數值 M,取其餘數當作X的位址。這位址介於0~M-1間。一般M建議使用質數效果較佳(不會有因數消去之問題)

h(X)= X mod M

【範例】假設有一鍵值數列{X}={15,29,52,100,200}。以除數M=13,則依h(X)= X mod M,建立之雜湊表為:

X

X mod 13

位址

資料鍵值

15

0

52

29

1

 

52

2

15

100

3

29

200

4

 

 

5

200

 

6

 

 

7

 

 

8

 

 

9

100

 

10

 

 

11

 

 

12

 

 

數字分析法(digital analysis)

此方法需先對資料鍵值之分佈情形詳細分析再設計雜湊函數,數字分析法有兩種:

【目視數字分析法】利用目視法,將鍵值各位數的分佈不均的數字刪除,其餘保留為雜湊位址(hash address)

【統計數字分析法】運用統計方法分析鍵值各位數的分佈情形,求出雜湊位址(hash address)

解決溢位(overflow handling)

一般常見方法有:線性探測法(linear probing)、鏈結串列(chaining)、平方探測(quadratic probing)、再雜湊(rehashing)

線性探測法(linear probing)

又稱線性開放定址(linear open addressing)。將雜湊位址視為環狀空間,當溢位發生時,以線性方式找下一個空的儲存空間將資料存入。

【優點】容易使用。

【缺點】易產生「主要群集」問題,也就是一群資料有相近之hashing address之問題,長時間執行會增加平均搜尋時間。

鏈結串列(chaining)

將碰撞之資料(data)放到溢位資料區(overflow data area),並用指標連結。

【優點】容易使用。

【缺點】需求溢位資料區(overflow data area),需使用指標函數。

平方探測(quadratic probing)

此方法改善線性探測法之「主要群集」問題,可避免相近之鍵值聚在一起。當h(X)位址發生溢位時,下一次探測位址為

(h(X)+i2) mod b (h(X)-i2) mod b

其中,1i(b-1)/2b為可表示為4j+3型式之質數。

再雜湊(rehashing)

事先設計好一套雜湊函數 h1h2h3hm,當溢位時先使用h1,若再發生溢位則依次使用h2h3hm,至沒溢位發生或沒雜湊函數。

返回首頁