查找:二分法的递归实现与迭代实现

       对于已经排好序的数组,可以用二分法进行查找,其时间复杂度要比遍历快,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);
} 

猜你喜欢

转载自blog.csdn.net/Bridge3/article/details/82497551