检索(查找)算法

1.顺序检索
注:题目要求只输入10个数
图片描述

#include <stdio.h>
int search(int a[],int x); 
int main()
{
	int a[10];
	for(int i=0;i<10;i++)scanf("%d",&a[i]);
	int key;
	scanf("%d",&key);
	int r=search(a,key);
	if(r>=0)printf("find %d in a[%d]",key,r);
	else printf("not find %d",key);

	return 0;
}
int search(int a[],int x){int j;
	for(j=9;j>=0&&a[j]!=x;j--){
		;
	}
	return j;
	
}

需要注意的是, search查找函数中的j>=0与a[j]!=x不能颠倒位置。这是因为对于逻辑运算符&&,若&&前面的那个条件不满足,其不会再检查后面的表达式,可能会出现数组下标越界的情况。

递归实现
例题:题目名称:顺序检索

题目描述:编写程序,用递归方法在整数组中进行顺序检索。

输入:

第一行输入一个正整数n(0<n≤100),表示数组的元素个数;

第二行依次输入n个整数,作为数组的元素;

第三行输入待检索的关键字。

输出:

如果数组中含有关键字,则输出其首次出现的位置(下标值较小的位置)否则输出NULL。

样例1:

输入:
8
0 2 3 4 5 9 10 8
3
输出:
2
样例2:

输入:
8
0 2 3 4 5 9 10 8
6
输出:
NULL

#include <stdio.h>
int n, k;
int a[100];

int f(int i)
{
	if (a[i] == k)return i;
	else if (i == n-1)return -1;
	return f(i + 1);
}
int main() {
	scanf("%d",&n);
	int i = 0;
	for (int i = 0; i < n; i++)scanf("%d",&a[i]);
	scanf("%d",&k);
	if (f(0) != -1)printf("%d",f(0));
	else printf("NULL");
	return 0;
}

此解法的一大亮点在于使用了全局变量,好处是在自定义函数中和主调函数中不用重复定义变量。其实如果不使用全局变量也可以做到,但是在设置形参和传值的过程中变量会比较多,可能会不太方便。
本题的查找函数部分,如果使用以下形式则不成功:

int check(int a[],int n,int key){
	int i=0;
	if(a[i]==key) return i;
	else return check(a,n-1,key);
}

原因在于:
①思路不清晰:一般的顺序检索是由第n-1项逐渐向前查找,但本题要求输出较小的下标。若在设计check函数的时候形参就有n,递归的关键之处在于重复调用自身来实现与循环相同的功能,由于则在第四行代码处调用check函数时一定会出现n-1,这就使得check函数是从第n-1项开始查找,无法实现。
②基本语法还不够扎实。在上面的算法中可以看到,
if (a[i] == k)return i; else if (i == n)return -1;
这里是比较巧妙的。一般我们在做if else if的时候,两个括号内的判断语句是一样的,但这里的else if却实现了“a[i]!=k&&i==n”的功能,即数组a一直到最后一项都没有查找到关键字

2.对半检索(二分查找)

完整代码如下:

#include <stdio.h>
int mid;
int search (int a[],int key,int lower,int upper,int n);
int main()
{
	int a[999],n,upper,lower;
	scanf("%d",&n);
	lower=0;
	upper=n-1;
	for(int i=0;i<n;i++)scanf("%d",&a[i]);
	int key;
	scanf("%d",&key);
	if(search(a,key,lower,upper,n)==-1)printf("not found");
	else printf("find %d in a[%d]",key,search(a,key,lower,upper,n));
	
	return 0;
}
int search (int a[],int key,int lower,int upper,int n){

	while(upper>=lower){
		mid=(upper+lower)/2;
		if(key==a[mid])return mid;
		else{
			if(key<a[mid])upper=mid-1;
			else lower = mid+1;
		}	
	}
	return -1;
}

巧记:key<mid: upper=mid-1;
key>mid: lower=mid+1;

另:search查找函数部分可以由递归实现。

#include <stdio.h>
int mid;
int search (int a[],int key,int lower,int upper,int n);
int main()
{
	int a[999],n,upper,lower;
	scanf("%d",&n);
	lower=0;
	upper=n-1;
	for(int i=0;i<n;i++)scanf("%d",&a[i]);
	int key;
	scanf("%d",&key);
	if(search(a,key,lower,upper,n)==-1)printf("not found");
	else printf("find %d in a[%d]",key,search(a,key,lower,upper,n));
	
	return 0;
}
int search (int a[],int key,int lower,int upper,int n){
	
//	while(upper>=lower){
		mid=(upper+lower)/2;
		if(key==a[mid])return mid;
		else{
			if(key<a[mid]) return search(a,key,lower,mid-1,n);
			if(key>a[mid]) return search(a,key,mid+1,upper,n);
		}	
//	}
	return -1;
}

:将循环改成递归的关键之处在于将循环的条件合理地删去,并改成重复调用自身的递归函数。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值