1. 程式人生 > >(轉載)查找一 線性表的查找

(轉載)查找一 線性表的查找

while 時間 -i 它的 操作 限制 ise 進行 鏈表

查找一 線性表的查找

目錄
  • 查找的基本概念
  • 順序查找
  • 二分查找
  • 分塊查找
  • 三種線性查找的PK
  • 參考資料
  • 相關閱讀

查找的基本概念


什麽是查找?

查找是根據給定的某個值,在表中確定一個關鍵字的值等於給定值的記錄或數據元素。

查找算法的分類

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

否則,稱之為靜態查找表

此外,如果查找的全過程都在內存中進行,稱之為內查找

反之,如果查找過程中需要訪問外存,稱之為外查找

查找算法性能比較的標準

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

由於查找算法的主要運算是關鍵字的比較過程,所以通常把查找過程中對關鍵字需要執行的平均比較長度

(也稱為平均比較次數)作為衡量一個查找算法效率優劣的比較標準。

技術分享

選取查找算法的因素

(1) 使用什麽數據存儲結構(如線性表、樹形表等)。

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

順序查找


要點

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

存儲結構

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

基本思想

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

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

核心代碼

技術分享 public int orderSearch(int[] list, int length, int key) {
// 從前往後掃描list數組,如果有元素的值與key相等,直接返回其位置
for (int i = 0; i < 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 class BlockSearch {

    class IndexType {
        public int key; // 分塊中的最大值
        public int link; // 分塊的起始位置
    }

    // 建立索引方法,n 是線性表最大長度,gap是分塊的最大長度
    public IndexType[] createIndex(int[] list, int n, int gap) {
        int i = 0, j = 0, max = 0;
        int num = n / gap;
        IndexType[] idxGroup = new IndexType[num]; // 根據步長數分配索引數組大小

        while (i < num) {
            j = 0;
            idxGroup[i] = new IndexType();
            idxGroup[i].link = gap * i; // 確定當前索引組的第一個元素位置
            max = list[gap * i]; // 每次假設當前組的第一個數為最大值
            // 遍歷這個分塊,找到最大值
            while (j < gap) {
                if (max < list[gap * i + j]) {
                    max = list[gap * i + j];
                }
                j++;
            }
            idxGroup[i].key = max;
            i++;
        }

        return idxGroup;
    }

    // 分塊查找算法
    public int blockSearch(IndexType[] idxGroup, int m, int[] list, int n, int key) {
        int mid = 0;
        int low = 0;
        int high = m -1;
        int gap = n / m; // 分塊大小等於線性表長度除以組數
        
        // 先在索引表中進行二分查找,找到的位置存放在 low 中
        while (low <= high) {
            mid = (low + high) / 2;
            if (idxGroup[mid].key >= key) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }

        // 在索引表中查找成功後,再在線性表的指定塊中進行順序查找
        if (low < m) {
            for (int i = idxGroup[low].link; i < idxGroup[low].link + gap; i++) {
                if (list[i] == key)
                    return i;
            }
        }

        return -1;
    }

    // 打印完整序列
    public void printAll(int[] list) {
        for (int value : list) {
            System.out.print(value + " ");
        }
        System.out.println();
    }

    // 打印索引表
    public void printIDX(IndexType[] list) {
        System.out.println("構造索引表如下:");
        for (IndexType elem : list) {
            System.out.format("key = %d, link = %d\n", elem.key, elem.link);
        }
        System.out.println();
    }

    public static void main(String[] args) {
        int key = 85;
        int array[] = { 8, 14, 6, 9, 10, 22, 34, 18, 19, 31, 40, 38, 54, 66, 46, 71, 78, 68, 80, 85 };
        BlockSearch search = new BlockSearch();
        
        System.out.print("線性表: ");
        search.printAll(array);

        IndexType[] idxGroup = search.createIndex(array, array.length, 5);
        search.printIDX(idxGroup);
        int pos = search.blockSearch(idxGroup, idxGroup.length, array,
                array.length, key);
        if (-1 == pos) {
            System.out.format("查找key = %d失敗", key);
        } else {
            System.out.format("查找key = %d成功,位置為%d", key, pos);
        }
    }

}

分塊查找之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

算法分析

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

三種線性查找的PK


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

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

(3) 從存儲結構而言,順序查找和分塊查找既可用於順序表也可用於鏈表;而二分查找只適用於順序表。

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

(轉載)查找一 線性表的查找