順序查找
基本思想
- 屬於線性查找和無序查找,從一端開始順序掃描,直到找到與目標值value相等的元素。
- 這是最基本的查找方法,也是時間複雜度最高的查找算法。
- 在數據過多時,這種方法並不適用。
代碼實現
public Type SequenceSearch(Type[] list,Type t)
{
for(Type temp : list)
{
if(temp.equals(t))
return temp;
}
return null;
}
分塊查找
基本思想
- 屬於順序查找的改進方法,又叫索引順序查找。
- 將n個元素分成m塊(m<=n),每個塊中元素可以沒有順序,但是m個塊之間是有序排列,所以特別適合於節點動態變化的情況。
- 分塊查找的速度雖然不如二分查找算法,但比順序查找算法快得多,同時又不需要對全部節點進行排序。當節點很多且塊數很大時,對索引表可以採用折半查找,這樣能夠進一步提高查找的速度。
- 那麼索引表的構成就是每個塊中的最大元素。
- 查找方式是先對索引表進行二分或順序查找,選出目標值應該所在的塊,然後在塊內進行順序查找。
二分查找
基本思想
- 屬於有序查找算法,也叫折半查找,就是將數組每次選取一半進行查找,怎麼選取一半就需要讓中間值與目標值value進行比較,因爲有序,所以中間值小於目標值則選取後半部分,大於目標值則選取前半部分,依此類推,直到找出與目標值相等的元素,否則返回-1或null。
- 這種方法有效的縮減查找次數和查找範圍,適用於數據量比較大的有序表。
- 因爲前提是有序表,所以對於插入刪除等操作過多的數據集並不適用,因爲在排序算法上浪費的時間會比較多。
- 一般的時間複雜度是O(log2n)
代碼實現
public int BinarySearch(int[] list,int value)
{
int low = 0,high = list.length-1,mid;
while (low<=high)
{
mid = (low+high)/2;
if(list[mid] == value)
return mid;
if(list[mid]>value)
high = mid-1;
if(list[mid]<value)
low=mid+1;
}
return -1;
}
public int BinarySearch(int[] list,int value,int low,int high)
{
int mid = (low+high)/2;
if(list[mid] == value)
return mid;
if(list[mid]>value)
return BinarySearch(list,value,low,mid-1);
if(list[mid]<value)
return BinarySearch(list,value,mid+1,high);
else
return -1;
}
插值查找
基本思想
- 屬於二分查找的改進版,二分查找一直重複一半一半的操作,這種操作比較固定,並不會根據目標值的大小進行自適應分段和選擇,而插值查找可以根據目標值value進行自適應。
- 下面是百度詞條對插值的解釋:插值類似於平常查英文字典的方法,在查一個以字母C開頭的英文單詞時,決不會用二分查找,從字典的中間一頁開始,因爲知道它的大概位置是在字典的較前面的部分,因此可以從前面的某處查起。
- 既然是二分查找的改進版,那麼就要找關鍵點進行改進,二分是取1/2的有序表進行查找,那麼mid就是關鍵點,二分中mid=(low+high)/2,可以轉化成mid=low+(high-low)/2,所以相當於(high-low)/2中的1/2就是所分的比例,那麼可以對mid進行改進,mid=low+low+(value-list[low])/(list[high]-list[low])*(high-low),(value-list[low])/(list[high]-list[low])就是所分的比例。
- 根據目標值在整個有序表中所處的位置,讓mid的變化更靠近目標值value,這樣也就間接地減少了比較次數。
- 這種方法適用於關鍵字分佈均勻的有序表。
- 複雜度爲O(log2(log2n))
代碼實現
public int InsertSearch(int[] list,int value,int low,int high)
{
int mid = low+(value-list[low])/(list[high]-list[low])*(high-low);
if(list[mid] == value)
return mid;
if(list[mid]>value)
return InsertSearch(list,value,low,mid-1);
if(list[mid]<value)
return InsertSearch(list,value,mid+1,high);
else
return -1;
}
斐波那契查找
基本思想
- 斐波那契數列與0.618有着奇妙的關聯,隨着斐波那契數列的遞增,前後兩個數的比值會越來越接近0.618,所以可以將黃金比例運用到查找中。
- 百度詞條:斐波那契搜索,斐波那契搜索就是在二分查找的基礎上根據斐波那契數列進行分割的。在斐波那契數列找一個等於略大於查找表中元素個數的數F(n),將原查找表擴展爲長度爲F(n)(如果要補充元素,則補充重複最後一個元素,直到滿足F[n]個元素),完成後進行斐波那契分割,即F[n]個元素分割爲前半部分F[n-1]個元素,後半部分F[n-2]個元素,找出要查找的元素在那一部分並遞歸,直到找到。
- 這個方法比較重要,所以百度詞條上講的很清楚!
代碼實現
package Searching;
import java.util.Arrays;
public class Fibonaccialo {
public static void main(String[] args) {
int arr[] = {2,4,9,10,13,15,16,19,34};
System.out.println(FibonacciSearch(arr,34)+1);
}
public static int[] Fibonacci(int n) {
int[] FibonacciList = new int[n];
FibonacciList[0] = 0;
FibonacciList[1] = 1;
for (int i = 2; i < n; i++) {
FibonacciList[i] = FibonacciList[i - 1] + FibonacciList[i -2];
}
return FibonacciList;
}
public static int FibonacciSearch(int[] list,int value)
{
int low = 0;
int high = list.length -1;
int k = 0;
int mid = 0;
int f[] = Fibonacci(20);
while (high>f[k] - 1){
k++;
}
int temp[] = Arrays.copyOf(list,f[k]);
for (int i = high+1; i <temp.length ; i++) {
temp[i] = list[high];
}
while (low<=high){
mid = low+f[k-1]-1;
if(value<temp[mid]){
high = mid - 1;
k--;
}else if(value>temp[mid]){
low = mid + 1;
k-=2;
}else{
if(mid<=high){
return mid;
}else {
return high;
}
}
}
return -1;
}
}
總結
- 還剩下兩種非常重要的查找算法,就是樹表和哈希,這兩種我就單獨寫,ball ball大佬們不要嫌棄!