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;
}
注:将循环改成递归的关键之处在于将循环的条件合理地删去,并改成重复调用自身的递归函数。