查找,在当今大数据时代是十分频繁需要进行的操作,在数据库软件中也是非常重要的功能之一,所以,一个好的查找算法也够大大节省计算机资源以及节省时间,大大提高效率。
下面将分别介绍顺序查找、二分查找和哈希查找算法
#define LEN 10
#define swap(a,b) {typeof(a) t=a;a=b;b=t;}
#define show_arr(arr,len) {for(int i=0;i<len;printf("%d ",arr[i++]));}
1、顺序查找
顺序查找,即对待查找的数据没有要求,从头到尾逐一比较,在小规模的查找中较为常见,查找效率较低。时间复杂度:O(N)
//顺序查找
int order_search(int *arr,int len,int key)
{
for(int i=0;i<len;i++)
{
if(key==arr[i])
return i;
}
return -1;
}
2、二分查找(折半查找)
待查找的数据必须有序,从数据中间位置开始比较查找,如果中间值比key小,则从左边继续进行二分查找,反之从右边进行。时间复杂度:O(logN)
因为二分查找要求数据是有序的所以这里我们顺便写个冒泡排序,用来保证传入的数列有序
//排序
void sort(int *arr,int len)
{
for(int i=0;i<len-1;i++)
{
for(int j=i+1;j<len;j++)
{
if(arr[j]<arr[i])
{
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
}
//二分查找循环
int bin_search(int *arr,int len,int key)
{
sort(arr,len);
if(key>arr[len/2])
{
for(int i=len/2+1;i<len;i++)
{
if(key==arr[i]) return i;
}
}
else if(key<arr[len/2])
{
for(int i=0;i<len/2;i++)
{
if(key==arr[i]) return i;
}
}
else if(key==arr[len/2])
return len/2;
return -1;
}
//二分查找递归法
int _digui_search(int *arr,int l,int r,int key)
{
if(l>r) return -1;
int m=(l+r)/2;
if(arr[m]==key) return m;
if(key<arr[m]) return _digui_search(arr,l,m-1,key);
else return _digui_search(arr,m+1,r,key);
}
int digui_search(int *arr,int len,int key)
{
return _digui_search(arr,0,len-1,key);
}
3、块查找(权重查找)
是一种数据处理的思想,不是一种特定的算法,当数据量非常多时,可以先把数据进行分块处理,然后再根据分块的条件进行查找,例如英文字典。
4、哈希查找(Hash)
数据 经过 哈希函数 计算出数据在哈希表中的位置,然后标记位置,方便之后的查找,它的时间复杂度最高可以达到 O(1)
但是该算法有很大的局限性,不适合负数、浮点型数据、字符型数据的查找,还需要额外申请存储空间,空间复杂度高,是一种典型的以空间换时间的算法
哈希函数设计方法:
直接定址法:直接把数据当做哈希表的下标,把哈希表中该下标的位置+1
数据分析法:分析数据的特点来设计哈希函数,常用的方法是找到最大值和最小值,用 最大值-最小值+1 确定哈希表的长度,使用 数据-最小值 作为哈希表的下标访问哈希表
平方取中法、折叠法、随机数法,但都无法保证哈希数据的唯一性,出现所谓的哈希冲突,一般使用链表解决
Hash函数的应用:MD5、SHA-1都属于Hash算法中的应用
//哈希查找
int hash_search(int *arr,int len,int key)
{
//直接定址法
//创建哈希表
/*int hash[100000]={};
for(int i=0;i<len;i++)
{
hash[arr[i]]++;
}
return hash[key];*/
int max=arr[0],min=arr[0];
for(int i=1;i<len;i++)
{
if(arr[i]>max) max=arr[i];
if(arr[i]<min) min=arr[i];
}
//创建哈希表
int hash[max-min+1];
memset(hash,0,sizeof(hash));
for(int i=0;i<len;i++)
{
hash[arr[i]-min]++;
}
//查找
return key-min;
}
测试一下各个算法:
int main(int argc,const char* argv[])
{
int arr[LEN]={};
for(int i=0;i<LEN;i++)
{
arr[i]=rand()%100;
printf("%d ",arr[i]);
}
printf("\n");
//printf("order search:%d\n",order_search(arr,LEN,77));
//sort(arr,LEN);
printf("循环二分:%d\n",bin_search(arr,LEN,92));
printf("递归二分:%d\n",digui_search(arr,LEN,92));
//for(int i=0;i<LEN;i++) printf("%d ",arr[i]);
show_arr(arr,LEN);
printf("\n");
printf("%d\n",hash_search(arr,LEN,49));
return 0;
}
简单介绍一下以上查找算法以及其代码实现
over