顺序查找
对待查找的数据没有要求,从头到尾逐一比较,在小规模的查找中较为常见,查找效率较低
时间复杂度:O(N)
int search_order(int *a,int len,int x){
for(int i = 0;i<len;i++){
if(a[i] == x)
return i;
}
return -1;
}
二分查找(折半查找)
待查找的数据必须有序,从数据中间位置开始比较查找,如果中间值比key小,则从左边继续进行二分查找,反之从右边进行。
时间复杂度:O(logN)
//二分查找 --递归版
int search_binary(int *a,int min,int max,int x){
if(min <= max){
int mid = (min+max)/2;
if(a[mid] == x){
return mid;
}else if(a[mid] > x){
max = mid-1;
return search_binary(a,min,max,x);
}else{
min = mid +1;
return search_binary(a,min,max,x);
}
}else{
return -1;
}
}
//二分查找 --循环版
int search_bin_for(int *a,int min,int max,int x){
while(min<=max){
int mid = (min+max)/2;
if(a[mid]==x) return mid;
if(a[mid] > x)
max = mid+1;
if(a[mid] < x)
min = mid+1;
}
return -1;
}
块查找(权重查找)
是一种数据处理的思想,不是一种特定的算法,当数据量非常多时,可以先把数据进行分块处理,然后再根据分块的条件进行查找,例如英文字典
#include<stdio.h>
#include<stdlib.h>
typedef struct Block{
int max;//存储该分块的最大值,作为查找条件
int start;
int end;
}Block;
int search_block(Block *block,int *a,int blen,int x){
int i =0 ;
//先确认在哪个分块
while(x > block[i].max && i<blen){
i++;
}
//再对这个块内的元素进行顺序查找
for(int j = block[i].start;j<block[i].end;j++){
if(x == a[j])
return j;
}
return -1;
}
int main(int argc, const char* argv[])
{
int a[12] = {16,5,9,12,
21,18,32,23,
48,36,52,66};
Block block[3] = {
{16,0,3},
{32,4,7},
{66,8,11}
};
int blen = sizeof(block)/sizeof(block[0]);
int index = search_block(block,a,blen,18);
printf("分块查找的下标为:%d",index);
return 0;
}
哈希查找(Hash)
数据 经过 哈希函数 计算出数据在哈希表中的位置,然后标记位置,方便之后的查找,它的时间复杂度最高可以达到 O(1)
但是该算法有很大的局限性,不适合负数、浮点型数据、字符型数据的查找,还需要额外申请存储空间,空间复杂度高,是一种典型的以空间换时间的算法
哈希函数设计方法:
直接定址法:直接把数据当做哈希表的下标,把哈希表中该下标的位置+1
数据分析法:分析数据的特点来设计哈希函数,常用的方法是找到最大值和最小值,用 最大值-最小值+1 确定哈希表的长度,使用 数据-最小值 作为哈希表的下标访问哈希表
平方取中法、折叠法、随机数法,但都无法保证哈希数据的唯一性,出现所谓的哈希冲突,一般使用链表解决
Hash函数的应用:MD5、SHA-1都属于Hash算法中的应用