查找,应该是最常用的算法之一了吧,当然还有排序,其实,查找是建立在排序基础上的,除了那个最笨的顺序查找。。。
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 查找分两个部分:先对索引表进行二分查找或顺序查找,以确定待查记录在哪一块中;然后,在已确定的块中用顺序法进行查找。