对于已经排好序的数组,可以用二分法进行查找,其时间复杂度要比遍历快,O(log N)。二分查找算法主要注意边界问题,就很容易实现。其思想就是首先判断查找的数X是大于中间的数还是小于,若大于则查找右边,同时将中间下标加1作为左边界;否则查找左边,同时将中间下标减1作为右边界。依次反复查找,直到找到;左右边界相等则说明查找结束,没找到。
迭代法:
分析起来较复杂,但不会增加内存空间,下面是我写的线性表二分查找——迭代实现源程序:
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
#define NotFound 0
typedef int ElementType;
typedef int Position;
typedef struct LNode *List;
struct LNode {
ElementType Data[MAXSIZE];
Position Last; /* 保存线性表中最后一个元素的位置 */
};
List ReadInput(); /* 裁判实现,细节不表。元素从下标1开始存储 */
Position BinarySearch( List L, ElementType X );
int main()
{
List L;
ElementType X;
Position P;
L = ReadInput();
while(scanf("%d", &X)!=EOF)
{
P = BinarySearch( L, X );
printf("%d\n", P);
}
return 0;
}
List ReadInput()
{
List L;
int i;
L = (List)malloc(sizeof(struct LNode));
scanf("%d",&L->Last);
for(i = 1; i<=L->Last; i++)
scanf("%d",&L->Data[i]);
return L;
}
/* 你的代码将被嵌在这里 */
Position BinarySearch( List L, ElementType X )
{
Position m,f0,f1; /* f0下界,f1上届,m中间 */
/*
** 二分查找,迭代
*/
f0 = 1; f1 = L->Last;
m = (f0 + f1) / 2;
/*
** 注意:不能用中间下标m != f0 判断,
** 因为m = (f0 + f1) / 2;会导致上边界
** 漏判,m=(7+8)/2=7;
*/
while( X != L->Data[m] && f1 != f0 ){
// printf("f0=%d,f1=%d,m=%d\n",f0,f1,m);
if( X > L->Data[m] )
f0 = m+1;
else
f1 = m-1;
m = (f0 + f1) / 2;
}
if(X == L->Data[m])
return m;
else
return NotFound;
}
递归实现:
递归实现容易分析,尤其是对于复杂的问题,只要将功能抽象出来,就比较容易写。但是要主要两个问题:返回值与栈溢出,尽量少用递归,防止栈溢出。下面是我写的线性表二分查找——递归实现源程序:
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
#define NotFound 0
typedef int ElementType;
typedef int Position;
typedef struct LNode *List;
struct LNode {
ElementType Data[MAXSIZE];
Position Last; /* 保存线性表中最后一个元素的位置 */
};
List ReadInput(); /* 裁判实现,细节不表。元素从下标1开始存储 */
Position BinarySearch( List L, ElementType X );
int main()
{
List L;
ElementType X;
Position P;
L = ReadInput();
while(scanf("%d", &X)!=EOF)
{
P = BinarySearch( L, X );
printf("%d\n", P);
}
return 0;
}
List ReadInput()
{
List L;
int i;
L = (List)malloc(sizeof(struct LNode));
scanf("%d",&L->Last);
for(i = 1; i<=L->Last; i++)
scanf("%d",&L->Data[i]);
return L;
}
/* 你的代码将被嵌在这里 */
Position Find_digui( List L, ElementType X, Position Left, Position Right)
{
Position m = (Left + Right) / 2;
if( X == L->Data[m] ) /* 找到跳出 */
return m;
if(Left == Right)
return NotFound;
if( X > L->Data[m] ) /* 查找右边 */
return Find_digui( L, X, m+1, Right);
if( X < L->Data[m]) /* 查找左边 */
return Find_digui( L, X, Left, m-1);
}
Position BinarySearch( List L, ElementType X )
{
return Find_digui( L, X, 1, L->Last);
}