(轉載)查找一 線性表的查找
查找一 線性表的查找
目錄- 查找的基本概念
- 順序查找
- 二分查找
- 分塊查找
- 三種線性查找的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) 分塊查找綜合了順序查找和二分查找的優點,既可以較為快速,也能使用動態變化的要求。
(轉載)查找一 線性表的查找