###一、折半查找 折半查找(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)
❑缺点:对查找表中的数据有顺序要求,在进行查找前首先进行排序。如果需要将查找不成功的关键字数据添加到查找表中,则需要对查找表中的已有数据进行大量的移动操作。