折半查找

折半查找的描述

       折半查找是对一个有序数据集合所做的操作。查找开始时,首先找出有序集合中间的那个元素。如果此元素比要查找的元素大,就接着在较小的一个半区进行查找;反之,如果此元素比要查找的元素小,就在较大的一个半区进行查找。在每个更小的数据集中重复这个查找过程,直到找到要查找的元素或数据集不能再分割。

       折半查找能够应用于任何类型的数据,只要能将这些元素按某种规则进行排序。当待搜索的集合是相对静态的数据集时,此时使用折半查找法是最好的选择。

       折半查找法实质上是不断地将有序数据集进行对半分割,并检查每个分区的中间元素。通过变量left和right控制一个循环来查找元素(其中left和right是正在进行查找的数据集的两个边界值)。首先,将left和right分别设置成0和size-1。在循环的每次迭代过程中,将middle设置为left和right之间区域的中间值。如果处于middle的元素比目标元素小,将左索引值移动到middle的后一个元素的位置上,即下一组要搜索的区域是当前数据集的上半区。如果处于middle的元素比目标值大,将右索引值移动到middle的前一个元素的位置,即下一组要搜索的区域是当前数据集的下半区。随着搜索的不断进行,left从左向右移,right从右向左移。一旦在middle处找到目标,查找将停止;如果目标没有找到,left和right将重合。

 

       算法:

BinarySearch(A[0...n-1], k)
 //实现非递归的折半查找
 //输入:一个升序的数组A[0...n-1],k为要查找的值
 //输出:一个数组元素的下标,该元素等于k;如果没有这样的元素,则返回-1
 left <- 0 ; right <- n-1
 while left <= right do 
     middle <- (left+right())/2
     if A[middle] > k  right <- middle-1
	 else if A[middle] < k left <- middle+1
	 else return middle
 return -1


 

折半查找的实现

// BinarySearch.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "typedef.h"

/*
*函数名:Compare_uint
*参数:pKey1  指向第一个比较元素的地址
*      pKey2  指向第二个比较元素的地址
*功能:比较两个元素的大小
*返回值:1 表示Key1 大于 Key2
*        -1 表示Key1 小于 Key2
*        0 表示Key1 等于 Key2
*作者:AlbertoNo1
*日期:2016-03-15
*/
INT32 Compare_uint(VOID *pKey1, VOID *pKey2)
{
	/*对两个无符号整型数进行比较*/
	if (*((UINT32*)pKey1) > *((UINT32*)pKey2))
	{
		return 1;
	}
	else if (*((UINT32*)pKey1) < *((UINT32*)pKey2))
	{
		return -1;
	}
	else
	{
		return 0;
	}
}

/*
*函数名:BinarySearch
*参数:pData  有序数组数据的首地址
*      uiSize 数据的元素个数
*      pTarget  待查找的目标元素
*      compare  两个元素的比较函数
*功能:在有序数组中折半查找指定数据
*返回值:-1 没找到  大于等于0 查找元素所在的位置
*作者:AlbertoNo1
*日期:2016-03-29
*/
INT32 BinarySearch(VOID *pData, UINT32 uiSize, VOID *pTarget, INT32 (*compare)(VOID *pKey1, VOID *pKey2))
{
	INT32 iLeft = 0;
	INT32 iRight = 0;
	INT32 iMiddle = 0;

	UINT32 *puiData = NULL;

	puiData = (UINT32*)pData;

	iLeft = 0;
	iRight = uiSize-1;

	while (iLeft <= iRight)
	{
		iMiddle = (iLeft+iRight)/2;

		if (compare(&puiData[iMiddle], pTarget) > 0)
		{
			iRight = iMiddle - 1;
		} 
		else if (compare(&puiData[iMiddle], pTarget) < 0)
		{
			iLeft = iMiddle + 1;
		}
		else
		{
			return iMiddle;
		}
	}

	return -1;
}

int _tmain(int argc, _TCHAR* argv[])
{
	INT32 iPos = 0;
	UINT32 uiValue = 0;

	UINT32 auiData[] = {10,15,15,18,20,20,20,36,48,51,51,77,77};


	uiValue = 9;
	iPos = BinarySearch(auiData, sizeof(auiData)/sizeof(auiData[0]), &uiValue,Compare_uint);

	printf("BinarySearch Result: %d \n\n", iPos);


	uiValue = 10;
	iPos = BinarySearch(auiData, sizeof(auiData)/sizeof(auiData[0]), &uiValue,Compare_uint);

	printf("BinarySearch Result: %d \n\n", iPos);

	uiValue = 20;
	iPos = BinarySearch(auiData, sizeof(auiData)/sizeof(auiData[0]), &uiValue,Compare_uint);

	printf("BinarySearch Result: %d \n\n", iPos);

	uiValue = 77;
	iPos = BinarySearch(auiData, sizeof(auiData)/sizeof(auiData[0]), &uiValue,Compare_uint);

	printf("BinarySearch Result: %d \n\n", iPos);

	uiValue = 78;
	iPos = BinarySearch(auiData, sizeof(auiData)/sizeof(auiData[0]), &uiValue,Compare_uint);

	printf("BinarySearch Result: %d \n\n", iPos);

	getchar();
	return 0;
}


 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值