天天看點

查找一 線性表的查找查找的基本概念順序查找二分查找分塊查找三種線性查找的PK

什麼是查找?

查找是根據給定的某個值,在表中确定一個關鍵字的值等于給定值的記錄或資料元素。

查找算法的分類

若在查找的同時對表記錄做修改操作(如插入和删除),則相應的表稱之為動态查找表;

否則,稱之為靜态查找表。

此外,如果查找的全過程都在記憶體中進行,稱之為内查找;

反之,如果查找過程中需要通路外存,稱之為外查找。

查找算法性能比較的标準

——平均查找長度ASL(Average Search Length)

由于查找算法的主要運算是關鍵字的比較過程,是以通常把查找過程中對關鍵字需要執行的平均比較長度(也稱為平均比較次數)作為衡量一個查找算法效率優劣的比較标準。

選取查找算法的因素

(1) 使用什麼資料存儲結構(如線性表、樹形表等)。

(2) 表中的次序,即對無序表還是有序表進行查找。

要點

它是一種最簡單的查找算法,效率也很低下。

存儲結構

沒有存儲結構要求,可以無序,也可以有序。

基本思想

從資料結構線形表的一端開始,順序掃描,依次将掃描到的結點關鍵字與給定值k相比較,若相等則表示查找成功;

若掃描結束仍沒有找到關鍵字等于k的結點,表示查找失敗。

核心代碼

<a></a>

public int orderSearch(int[] list, int length, int key) {

    // 從前往後掃描list數組,如果有元素的值與key相等,直接傳回其位置

    for (int i = 0; i &lt; length; i++) {

        if (key == list[i]) {

            return i;

        }

    }

    // 如果掃描完,說明沒有元素的值比對key,傳回-1,表示查找失敗

    return -1;

}

算法分析

順序查找算法最好的情況是,第一個記錄即比對關鍵字,則需要比較 1 次;

最壞的情況是,最後一個記錄比對關鍵字,則需要比較 N 次。

是以,順序查找算法的平均查找長度為

ASL = (N + N-1 + ... + 2 + 1) / N = (N+1) / 2

順序查找的平均時間複雜度為O(N)。

二分查找又稱折半查找,它是一種效率較高的查找方法。

使用二分查找需要兩個前提:

(1) 必須是順序存儲結構。

(2) 必須是有序的表。

首先,将表中間位置記錄的關鍵字與查找關鍵字比較,如果兩者相等,則查找成功;

否則利用中間位置記錄将表分成前、後兩個子表,如果中間位置記錄的關鍵字大于查找關鍵字,則進一步查找前一子表,否則進一步查找後一子表。

重複以上過程,直到找到滿足條件的記錄,使查找成功,或直到子表不存在為止,此時查找不成功。

public int binarySearch(int[] list, int length, int key) {

    int low = 0, mid = 0, high = length - 1;

    while (low &lt;= high) {

        mid = (low + high) / 2;

        if (list[mid] == key) {

            return mid; // 查找成功,直接傳回位置

        } else if (list[mid] &lt; key) {

            low = mid + 1; // 關鍵字大于中間位置的值,則在大值區間[mid+1, high]繼續查找

        } else {

            high = mid - 1; // 關鍵字小于中間位置的值,則在小值區間[low, mid-1]繼續查找

二分查找的過程可看成一個二叉樹。

把查找區間的中間位置視為樹的根,左區間和右區間視為根的左子樹和右子樹。

由此得到的二叉樹,稱為二分查找的判定樹或比較樹。

由此可知,二分查找的平均查找長度實際上就是樹的高度O(log2N)。

分塊查找(Blocking Search)又稱索引順序查找。它是一種性能介于順序查找和二分查找之間的查找方法。

分塊查找由于隻要求索引表是有序的,對塊内節點沒有排序要求,是以特别适合于節點動态變化的情況。

分塊查找表是由“分塊有序”的線性表和索引表兩部分構成的。

所謂“分塊有序”的線性表,是指:

假設要排序的表為R[0...N-1],将表均勻分成b塊,前b-1塊中記錄個數為s=N/b,最後一塊記錄數小于等于s;

每一塊中的關鍵字不一定有序,但前一塊中的最大關鍵字必須小于後一塊中的最小關鍵字。

注:這是使用分塊查找的前提條件。

如上将表均勻分成b塊後,抽取各塊中的最大關鍵字和起始位置構成一個索引表IDX[0...b-1]。

由于表R是分塊有序的,是以索引表是一個遞增有序表。

下圖就是一個分塊查找表的存儲結構示意圖

分塊查找算法有兩個處理步驟:

(1) 首先查找索引表

因為分塊查找表是“分塊有序”的,是以我們可以通過索引表來鎖定關鍵字所在的區間。

又因為索引表是遞增有序的,是以查找索引可以使用順序查找或二分查找。

(2) 然後在已确定的塊中進行順序查找

因為塊中不一定是有序的,是以隻能使用順序查找。

代碼範例

 分塊查找之JAVA實作

運作結果

線性表: 8 14 6 9 10 22 34 18 19 31 40 38 54 66 46 71 78 68 80 85 

構造索引表如下:

key = 14, link = 0

key = 34, link = 5

key = 66, link = 10

key = 85, link = 15

查找key = 85成功,位置為19

因為分塊查找實際上是兩次查找過程之和。若以二分查找來确定塊,顯然它的查找效率介于順序查找和二分查找之間。

(1) 以平均查找長度而言,二分查找 &gt; 分塊查找 &gt; 順序查找。

(2) 從适用性而言,順序查找無限制條件,二分查找僅适用于有序表,分塊查找要求“分塊有序”。

(3) 從存儲結構而言,順序查找和分塊查找既可用于順序表也可用于連結清單;而二分查找隻适用于順序表。

(4) 分塊查找綜合了順序查找和二分查找的優點,既可以較為快速,也能使用動态變化的要求。

 本文轉自靜默虛空部落格園部落格,原文連結:http://www.cnblogs.com/jingmoxukong/p/4324179.html,如需轉載請自行聯系原作者

繼續閱讀