二分查找算法例题


一、问题描述

  对于给定11个数据元素的有序表:(2,3,10,15,20,25,28,29,30,35,40),若查找给定值为20的元素,将依次与表中哪些元素比较?若查找给定值为26的元素,将依次与哪些元素比较?假设查找表中每个元素的概率相同,求查找成功时的平均查找长度和查找不成功时的平均查找长度。

二、实现思路

  对于给定11个数据元素的有序表:(2,3,10,15,20,25,28,29,30,35,40),采用二分查找,若查找给定值为20的元素,共比较4次。若查找给定值为26的元素,依次与25,30,28元素比较,共比较3次。假设查找表中每个元素的概率相同,根据查找判定树图1可得,在查找成功时会找到某个内部结点,则成功时的ASL成功=(11+22+43+44)/11=3,在查找不成功时,会找到图中某个外部结点,则不成功时的平均查找长度为ASL不成功=(43+84)/12=3.67。
  折半查找的基本思路是设R[low…high]是当前的查找区间,首先确定该区间的中点位置mid=[(low+high)/2],然后将待查的k值与R[mid].key比较:
  (1)若k=R[mid].key,则查找成功并返回该元素的逻辑序号。
   (2)若k<R[mid]. key.则由表的有序性可知R[mid.high].key均大干k.因此若表中存在关键字等于k的元素,则该元素必定是在位置mid左边的子表R[low…mid-1]中,故新的查找区间是左子表R[low…mid-1]。
  (3)若k> R[mid].key.则关键字为k的元素必在mid的右子表R[mid+1…high]中。即新的查找区间是右子表R[mid+1…high],下一次查找是针对新的查找区间进行的。
图1 查找判定树
           图1 查找判定树

三、解题代码

#include <iostream>
#include<iomanip>

using namespace std;

#define MAX  50

typedef int KeyType;		//定义关键字类型
typedef int InfoType;

typedef struct
{
	KeyType key;			//关键字项
	InfoType data;			//其他数据类型
}RecType;					//查找元素的类型


//折半查找算法,返回查找元素位置并纪录比较路径
int BinSearch(RecType R[], int n, KeyType k,int cmp[])
{
	int count = 0;  //比较路径数组的下标
	int low = 0, high = n - 1, mid;
	while (low <= high)			//当前区间存在元素时循环
	{
		mid = (low + high) / 2;
		if (R[mid].key == k)	//查找成功返回其逻辑序号mid+1
		{
			cmp[count++] = R[mid].key;  //纪录比较路径
			cmp[count] = -1;			//作为路径结尾的标志
			return mid + 1;
		}
		if (R[mid].key > k)		//继续在R[low..mid-1]中查找
		{
			cmp[count++] = R[mid].key;
			high = mid - 1;
		}
		else
		{
			cmp[count++] = R[mid].key;
			low = mid + 1;		//继续在R[mid+1..high]中查找
		}
	}
	return 0;
}

int main()
{
	int n,key,i;
	RecType R[MAX];					//比较路径
	int cmp[MAX] = { 0 };
	cout << "请输入有序表中元素的个数:";
	cin >> n;
	cout << "请依次输入有序表中元素的个数:";
	for (int i = 0; i < n; i++)
	{
		cin >> R[i].key;
	}
	cout << "请输入查找关键字:";
	cin >> key;
	i = BinSearch(R, n, key, cmp);
	if (i == 0)
	{
		cout << "查找失败!";
		return 0;
	}
	cout << "查找关键字的位置为:"<<i<<endl;

	cout << "查找关键字的比较路径为:"<<endl;
	for (int i = 0; cmp[i]!= -1; i++)
	{
		cout <<cmp[i]<<" ";
	}
}

四、运行结果

在这里插入图片描述

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值