折半查找的描述
折半查找是对一个有序数据集合所做的操作。查找开始时,首先找出有序集合中间的那个元素。如果此元素比要查找的元素大,就接着在较小的一个半区进行查找;反之,如果此元素比要查找的元素小,就在较大的一个半区进行查找。在每个更小的数据集中重复这个查找过程,直到找到要查找的元素或数据集不能再分割。
折半查找能够应用于任何类型的数据,只要能将这些元素按某种规则进行排序。当待搜索的集合是相对静态的数据集时,此时使用折半查找法是最好的选择。
折半查找法实质上是不断地将有序数据集进行对半分割,并检查每个分区的中间元素。通过变量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;
}