1、順序查找
時間復雜度:O(n)
優點:算法簡單,對查找表的記錄沒有任何要求
缺點:效率低下
適用:數據量較少時的查找
原理:
在一個已知無(或有序)序隊列中找出與給定關鍵字相同的數的具體位置。原理是讓關鍵字與隊列中的數從最後一個開始逐個比較,直到找出與給定關鍵字相同的數為止。
int SequenceSearch(int *array, int size, int key) { int i; for(i=0; i<size; i++) { if(array[i]==key) { return i; } } return -1; }
int SequenceSearch(int *array, int size, int key) { int i=size-1; array[0]=key; //哨兵 while(key != array[i]) { i--; } return i; }
2、二分查找/折半查找
時間復雜度:O(logn)
優點:比較次數少,查找速度快,平均性能好;
缺點:要求待查表為有序表,且插入刪除困難。
適用:折半查找方法適用於不經常變動而查找頻繁的有序列表。
原理:
首先,假設表中元素是按升序排列,將表中間位置記錄的關鍵字與查找關鍵字比較,如果兩者相等,則查找成功;否則利用中間位置記錄將表分成前、後兩個子表,如果中間位置記錄的關鍵字大於查找關鍵字,則進一步查找前一子表,否則進一步查找後一子表。重復以上過程,直到找到滿足條件的記錄,使查找成功,或直到子表不存在為止,此時查找不成功。
int BinarySearch(int *array, int size, int key) { int first,last,middle; first=0; last =size; while(first<=last) { middle = (first+last)/2; if(array[middle] < key) first=middle+1; else if(array[middle] > key) last=middle-1; else return middle; } return -1; }
3、插值查找
時間復雜度:O(logn)適用:數據量較大,而關鍵字分布又比較均勻的查找表
原理:
英漢字典中尋找單詞“worst”,我們決不會仿照對半查找那樣,先查找字典中間的元素,然後查找字典四分之三處的元素等等. 事實上,我們是在所期望的地址(在字典的很靠後的地方)附近開始查找的。
int InsertSearch(int *array, int size, int key) { int first,last,position; first=0; last =size-1; while(first<=last) { position = first+ (last-first)*(key-array[first])/(array[last]-array[first]); if(array[position] < key) first=position+1; else if(array[position] > key) last=position-1; else return position; } return -1; }
4、斐波那契查找
時間復雜度:O(logn)
原理:
#include<stdio.h> #include<stdlib.h> #include<string.h> int F[100]; int FibonacciSearch(int *a,int n,int key) { int low,high,mid,i,k=0; low=1; /* 定義最低下標為記錄首位 */ high=n; /* 定義最高下標為記錄末位 */ while(n>F[k]-1) k++; for (i=n;i<F[k]-1;i++) a[i]=a[n]; while(low<=high) { mid=low+F[k-1]-1; if (key<a[mid]) { high=mid-1; k=k-1; } else if (key>a[mid]) { low=mid+1; k=k-2; } else { if (mid<=n) return mid; /* 若相等則說明mid即為查找到的位置 */ else return n; } } return -1; } int main() { int i; int arr[]={0,1,16,24,35,47,59,62,73,88,99}; F[0]=0; F[1]=1; for(i = 2;i < 100;i++) { F[i] = F[i-1] + F[i-2]; } printf("%d\n", FibonacciSearch(arr,sizeof(arr)/sizeof(int)-1,99)); return 0; }
5、哈希查找
時間復雜度:O(1)
適用:數據本身是無法排序、無法比較
原理:
通過記錄數據元素與存儲地址的關系,直接定位數據元素的一種方法。
#include "stdio.h" #include "stdlib.h" #include "io.h" #include "math.h" #include "time.h" #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define MAXSIZE 100 /* 存儲空間初始分配量 */ #define SUCCESS 1 #define UNSUCCESS 0 #define HASHSIZE 12 /* 定義散列表長為數組的長度 */ #define NULLKEY -32768 typedef int Status; /* Status是函數的類型,其值是函數結果狀態代碼,如OK等 */ typedef struct { int *elem; /* 數據元素存儲基址,動態分配數組 */ int count; /* 當前數據元素個數 */ }HashTable; int m=0; /* 散列表表長,全局變量 */ /* 初始化散列表 */ Status InitHashTable(HashTable *H) { int i; m=HASHSIZE; H->count=m; H->elem=(int *)malloc(m*sizeof(int)); for(i=0;i<m;i++) H->elem[i]=NULLKEY; return OK; } /* 散列函數 */ int Hash(int key) { return key % m; /* 除留余數法 */ } /* 插入關鍵字進散列表 */ void InsertHash(HashTable *H,int key) { int addr = Hash(key); /* 求散列地址 */ while (H->elem[addr] != NULLKEY) /* 如果不為空,則沖突 */ { addr = (addr+1) % m; /* 開放定址法的線性探測 */ } H->elem[addr] = key; /* 直到有空位後插入關鍵字 */ } /* 散列表查找關鍵字 */ Status SearchHash(HashTable H,int key,int *addr) { *addr = Hash(key); /* 求散列地址 */ while(H.elem[*addr] != key) /* 如果不為空,則沖突 */ { *addr = (*addr+1) % m; /* 開放定址法的線性探測 */ if (H.elem[*addr] == NULLKEY || *addr == Hash(key)) /* 如果循環回到原點 */ return UNSUCCESS; /* 則說明關鍵字不存在 */ } return SUCCESS; } int main() { int arr[HASHSIZE]={12,67,56,16,25,37,22,29,15,47,48,34}; int i,p,key,result; HashTable H; key=39; InitHashTable(&H); for(i=0;i<m;i++) InsertHash(&H,arr[i]); result=SearchHash(H,key,&p); if (result) printf("查找 %d 的地址為:%d \n",key,p); else printf("查找 %d 失敗。\n",key); for(i=0;i<m;i++) { key=arr[i]; SearchHash(H,key,&p); printf("查找 %d 的地址為:%d \n",key,p); } return 0; }