您的位置:首页 > 其它

查找算法一之顺序查找 二分查找

2014-04-21 16:09 323 查看
上一节介绍了常见的排序算法,今天这一节介绍基本的查找算法,本次查找算法涵盖了顺序查找、二分查找和哈希,其他的动态查找如二叉排序树、平衡二叉树和B树,由于涉及到树的相关基本操作,暂时还没有研究,所以这个以后看情况是否补充进来。

以下由于部分代码使用了"哨兵",所以a[0]不用,都是从1开始,这样正好返回的下标就是该值所在数组中的位置

首先是传统的顺序查找,代码如下:

int sequenceSearch(int a[],int n,int key){
int i;
for(i=1;i<=n;i++){
if(a[i]==key) return i;
}
return 0;
}


按照数据结构书上改进的顺序查找,就是设置一个哨兵,可以解决不需要每次都判断是否满足循环条件i<=n的边界条件,代码如下:

int sequenceSearch2(int a[],int n,int key){
a[0]=key;
int i;
for(i=n;a[i]!=key;i--);
return i;
}
根据大话数据结构的说法,这种改进的算法免去了查找过程中每一次比较后都要判断查找位置是否越界的小技巧,看似于原先差别不大,但在总数据较多时,效率提高很大,是非常好的编码技巧。当然"哨兵"可以放在a[0]数组开始,也可以放在末尾。如果放在末尾,代码应该差不多,就是a
=key,然后从0开始查找,判断返回值是否为n,如果是n,则没找到,在0到n就查找成功。当然一比较还是放在开始更加方便。我还是疑惑这个到底能有多大效率的提高?

顺序查找的平均查找长度ASL是(n+1)/2

二分查找,又称折半查找,只适用于有序表,而且限于顺序存储结构,对链表无法有效进行折半查找,代码如下:

int binarySearch(int a[],int low,int high,int key){
int mid;
while(low<=high){
mid=(high+low)/2;
if(a[mid]==key){
return mid;
}
else if(a[mid]>key){
high=mid--;
}
else{
low=mid++;
}
}
return 0;
}

折半查找,对任意的n,当n较大时(n>50),近似结果:ASL=log2(n+1)-1

在c语言的函数库中,折半查找和快排一样也有现成的函数,bsearch函数,前提是数组必须有序,如果数组尚未排序,其结果未定义。

函数原型:void *bsearch(void const *key, void const *base, size_t n_elements, size_t el_size, int (*compare)(void const * , void const *);

第1个参数指向你需要查找的值,第2个参数指向查找所在的数组,第3个参数指定数组中元素的数目,第4个参数是每个元素的长度(以字符为单位)。第5个参数是和qsort中相同的指向比较函数的指针。bsearch函数返回一个指向查找到的数组元素的指针。如果需要查找的值不存在,函数返回一个NULL指针。(摘自 c和指针)

代码如下

int compare (void const *a, void const *b)
{
return *(int *)a-*(int *)b;
}

int lookup(int key,int num[])
{
int *pos;
pos = bsearch (&key, &num[1], MAXN-1, sizeof(int), compare);
return (pos != NULL);
}


查找算法相比较排序算法,更加容易理解,由于不涉及到树,代码量也不大,所以写代码基本没啥问题

总的代码:

#include <stdio.h>
#include <stdlib.h>
#define MAXN 13

int cmp(const void *a,const void *b){
return *(int *)a-*(int *)b;
}

void display(int a[],int n){
int i;
for(i=1;i<=n;i++){
if(i==n)
printf("%d",a[i]);
else
printf("%d ",a[i]);
}
printf("\n");
}

int sequenceSearch(int a[],int n,int key){ int i; for(i=1;i<=n;i++){ if(a[i]==key) return i; } return 0; }

int sequenceSearch2(int a[],int n,int key){ a[0]=key; int i; for(i=n;a[i]!=key;i--); return i; }

int binarySearch(int a[],int low,int high,int key){ int mid; while(low<=high){ mid=(high+low)/2; if(a[mid]==key){ return mid; } else if(a[mid]>key){ high=mid--; } else{ low=mid++; } } return 0; }

int compare (void const *a, void const *b)
{
return *(int *)a-*(int *)b;
}

int lookup(int key,int num[])
{
int *pos;
pos = bsearch (&key, &num[1], MAXN-1, sizeof(int), compare); //num[0]=0,下标从1开始
return (pos != NULL);
}

int main(int argc, char *argv[]) {
int num[]={0,12,67,56,16,25,37,22,29,15,47,48,34};
int flag=sequenceSearch(num,MAXN-1,12);
if(flag>0){
printf("sequence search:12 is found at position:%d\n",flag);
}
else{
printf("12 is not founded!\n");
}
flag=sequenceSearch2(num,MAXN-1,34);
if(flag>0){
printf("sequence search2:34 is found at position:%d\n",flag);
}
else{
printf("34 is not founded!\n");
}
num[0]=0;
qsort(num,MAXN,sizeof(num[0]),cmp);
display(num,12);
flag=binarySearch(num,1,MAXN-1,48);
if(flag>0){
printf("sequence search2:48 is found at position:%d\n",flag);
}
else{
printf("48 is not founded!\n");
}
if (lookup(1,num))
printf("1 is in the table.\n");
else
printf("1 isn't in the table.\n");
return 0;
}


未完待续,还有哈希查找

如需参考哈希查找,请链接:查找算法二之哈希查找

如果文章有什么错误或者有什么建议,欢迎提出,大家共同交流,一起进步

文章转载请注明出处,请尊重知识产权
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: