查找,應該是最常用的算法之一了吧,當然還有排序,其實,查找是建立在排序基礎上的,除了那個最笨的順序查找。。。
1. 好吧,首先來個最簡單的順序查找,原理很簡單,順序比較每個元素,直到找到關鍵字爲止
上代碼咯。。。
//順序查找:返回待查找關鍵字的索引(從0開始),數組存儲數據
int find_seq(int *a, int len, int value)
{
if(a == NULL || len == 0)
return -1;
for(int index=0; index<len; ++index)
{
if(value == a[index])
return index;
}
return -1; //沒找到
}
很顯然,順序查找複雜度爲O(n)
2. 來點高級的,二分查找,也叫做折半查找,應該範圍非常廣,很實用的說,當然有個坑爹的前提條件:數組有序
//二分查找:基於有序數組,查找每次從中間元素開始,然後每一次搜索都使得範圍縮小一半
int find_binary(int *a, int len, int value)
{
if(a == NULL || len == 0)
return -1;
int start = 0, end = len - 1;
while(start <= end)
{
int mid = start + ((end-start) >> 1);
if(a[mid] == value)
return mid;
else if(a[mid] > value)
end = mid - 1;
else
start = mid + 1;
}
return -1; //沒找到
}
經過分析,時間複雜度爲:O( log(n) ), 哈哈,比順序快了不少吧
3. 二叉排序樹,也稱二叉查找樹,是一種二叉樹結構,這種結構在查找方面有着天生的優勢。首先看看這棵樹長啥樣吧
哈哈,這棵樹很有特點:
若左子樹不空,那麼左子樹所有結點的值都小於它的根結點的值
若右子樹不空,那麼右子樹所有結點的值都大於它的根結點的值
//定義結點結構
typedef struct _NODE
{
int data;
struct _NODE* left;
struct _NODE* right;
}NODE;
NODE* find_BST(NODE* pNode, int value)
{
if(NULL == pNode)
return NULL;
if(value == pNode->data)
return pNode;
else if(value < pNode->data)
return find_BST(pNode->left, value);
else
return find_BST(pNode->right, value);
}
//用鏈表存儲數據
typedef struct _LINK_NODE
{
int data;
struct _LINK_NODE* next;
}LINK_NODE;
LINK_NODE* hash_find(LINK_NODE* array[], int mod, int data)
{
int index = data % mod;
if(NULL == array[index])
return NULL;
LINK_NODE* pLinkNode = array[index];
while(pLinkNode){
if(data == pLinkNode->data)
return pLinkNode;
pLinkNode = pLinkNode->next;
}
return pLinkNode;
}
。理論上來說,哈希查找只要O(1)的複雜度,因爲通過哈希函數求解下就可以直接定位了嘛,然後取值就行了。
5. 還有個應用很廣的查找算法,分塊查找,字典好像就是這麼幹的
基本思想:
分塊查找又稱索引順序查找,它是順序查找的一種改進方法。
方法描述:將n個數據元素"按塊有序"劃分爲m塊(m ≤ n)。每一塊中的結點不必有序,但塊與塊之間必須"按塊有序";即第1塊中任一元素的關鍵字都必須小於第2塊中任一元素的關鍵字;而第2塊中任一元素又都必須小於第3塊中的任一元素
操作步驟:
step1 先選取各塊中的最大關鍵字構成一個索引表;
step2 查找分兩個部分:先對索引表進行二分查找或順序查找,以確定待查記錄在哪一塊中;然後,在已確定的塊中用順序法進行查找。