查找——折半查找

###一、折半查找 折半查找(Binary Search)又称为二分查找。 注意 折半查找方法要求查找表的数据是线性结构保存,并且还要求查找表中的数据是按关键字由小到大有序排列。 ####折半查找的具体过程 假设有n个元素的查找表,首先计算位于查找表中间位置元素的序号m(m=n/2),取s[m]的关键字与给定值key进行比较。比较结果有3种可能 (1)若s[m]=key,表示查找成功。 (2)若s[m]>key,表示关键字key只可能在查找表的前半部分(因查找表中的数据是按从小到大的顺序排 列),则在前半部分继续进行折半查找。 (3)若s[m]<key,表示关键字key只可能在查找表的后半部分,则在后半部分继续进行折半查找。 技巧 从上面的过程可看出,折半查找是一种递归过程。每折半查找一次,可使查找范围缩小一半,当查找范 围缩小到只剩下一个元素,而该元素仍与关键字不相等,则说明查找失败。 在最坏的情况下,折半查找所需的比较次数为O(nlog 2 n),其查找效率比顺序查找法要快很多 例如,有以下数据: 6,12,28,37,54,65,69,83,90,92 若要查找关键字37,则查找过程如下图1:

输入图片说明

从上图1的查找过程可看出,通过4次比较,可找到关键字37所在的位置。再例如,若要查找关键字66,其查找过程如下图2:

输入图片说明

从上图2的过程可看出,通过4次比较,当查找范围缩小到只剩一个元素,仍没有找到指定关键字,说明查找失败。

###二、折半查找实现 ####折半查找法

/**
 *折半查找法(非递归)
 * */
int BinarySearch1(int s[], int n, int key)
{
	int low, high, mid;

	low = 0;
	high = n-1;
	while (low <= high) {		//查找结束条件,即至少包含一个元素
		mid = (low + high)/2;	//计算中间位置
		if (s[mid] == key)		//如果中间位置与关键字相同
			return mid;			//返回序号
		else if (s[mid] > key)	//中间元素大于关键字,关键字在左边
			high = mid - 1;		//重新定义high
		else					//中间元素大于关键字,关键字在右边
			low = mid + 1;		//重新定义low
	}
	return -1;
}

/**
 *折半查找法(递归)
 * */
int BinarySearch2(int s[], int low, int high, int key)
{
	int mid;

	if (low <= high) {			//查找结束条件,即至少包含一个元素
		mid = (low + high)/2;	//计算中间位置
		if (s[mid] == key)		//如果中间位置与关键字相同
			return mid;			//返回序号
		else if (s[mid] > key)	//中间元素大于关键字,关键字在左边
			return BinarySearch2(s, low, mid-1, key);
		else
			return BinarySearch2(s, mid+1, high, key);
	} else
		return -1;
}

####折半查找法测试

#include <stdio.h>
#include "BinarySearch.c"

#define ARRAYLEN 10
int main()
{
	int key, i, pos;
	int source[ARRAYLEN]={6, 12, 28, 37, 54, 65, 69, 83, 90, 92};

	/*折半查找,非递归*/
	printf("请输入查找关键字:");
	scanf("%d", &key);
	pos = BinarySearch1(source, ARRAYLEN, key);

	printf("原数据:");
	for (i=0; i< ARRAYLEN; i++)
		printf("%d ", source[i]);
	printf("\n");

	if (pos >= 0)
		printf("查找成功,关键字%d位于数组的第%d个位置\n", key, pos);
	else
		printf("查找失败,关键字%d不在数组中\n", key);

	/*折半查找,递归*/
	printf("请输入查找关键字:");
	scanf("%d", &key);
	pos = BinarySearch2(source, 0, ARRAYLEN-1, key);
	printf("原数据:");
	for (i=0; i< ARRAYLEN; i++)
		printf("%d ", source[i]);
	printf("\n");

	if (pos >= 0)
		printf("查找成功,关键字%d位于数组的第%d个位置\n", key, pos);
	else
		printf("查找失败,关键字%d不在数组中\n", key);
}

###三、折半查找特点 ❑优点:查找速度快,最多查找次数为O(nlog 2 n)

❑缺点:对查找表中的数据有顺序要求,在进行查找前首先进行排序。如果需要将查找不成功的关键字数据添加到查找表中,则需要对查找表中的已有数据进行大量的移动操作。

转载于:https://my.oschina.net/wangande2014/blog/701655

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值