如果静态查找表是一个有序表,则可以使用折半查找。
折半查找的过程是:先确定待查记录所在的范围(区间),然后逐步缩小范围直到找到或找不到该记录为止。折半查找过程是以处于区间中间位置记录的关键字和给定值比较,若相等,则查找成功,若不等,则缩小范围,直至新的区间中间位置记录的关键字等于给定值或者查找区间的大小小于零时(表明查找不成功)为止。
关键字key与表中某一元素array[i]比较,有3种情况:
1、key==array[i],查找成功
2、key > array[i],待查找元素可能的范围是array[i]之前
3、key < array[i],待查找元素可能的范围是array[i]之后
以如下有序表为例,分析折半查找的方法。
有序表如下:(05,13,19,21,37,56,64,75,80,88,92)
<一>查找有序表中存在的关键字,如查找21,查找过程如下:
(05,13,19,21,37,56,64,75,80,88,92)
↑ ↑ ↑
low = 0 mid = (low + high)/2 = 5 high = 10
① 因为array[mid] = 56 > 21,则令high = mid – 1; 说明待查元素若存在,必在区间[low, mid – 1]的范围内。
(05,13,19,21,37,56,64,75,80,88,92)
↑ ↑ ↑
low mid high = 5
②因为array[mid] = 19 < 21,则令low = mid + 1; 说明待查元素若存在,必在区间[mid + 1, high]的范围内。
(05,13,19,21,37,56,64,75,80,88,92)
↑ ↑
low/mid high = 5
③ 因为array[mid] = 21,说明待查元素存在。
<二>查找有序表中不存在的关键字,如查找85,查找过程如下:
(05,13,19,21,37,56,64,75,80,88,92)
↑ ↑ ↑
low = 0 mid = (low + high)/2 = 5 high = 10
① 因为array[mid] = 56 < 85,则令low = mid + 1; 说明待查元素若存在,必在区间[mid + 1, high]的范围内。
(05,13,19,21,37,56,64,75,80,88,92)
↑
low mid high
②因为array[mid] = 80 < 85,则令low = mid + 1; 说明待查元素若存在,必在区间[mid + 1, high]的范围内。
(05,13,19,21,37,56,64,75,80,88,92)
↑
low/mid high
③ 因为array[mid] = 88 > 85,则令high = mid – 1; 说明待查元素若存在,必在区间[low, mid -1]的范围内。
因为此时high小于low,所以查找失败。
有序表的折半查找C语言实现如下:
/*********************************************************************
Author:李冰 date:2014-9-24
Email:libing1209@126.com
*********************************************************************/
typedef int ElemType;
#define EQ(a, b) ((a) == (b))
#define LT(a, b) ((a) < (b))
#define LQ(a, b) ((a) <= (b))
int Search_Bin(ElemType array[], int num, int length)
{
int index_low, index_mid, index_high;
index_low = 1;
index_high = length;
while(index_low <= index_high){
index_mid = (index_low + index_high) / 2;
if(EQ(num, array[index_mid])) return index_mid + 1;
else if(LT(num , array[index_mid])) index_high = index_mid - 1;
else index_low = index_mid + 1;
}
return -1;
}
适用范围:对于规模较大的有序表查找,效率较高。适合很少改动但经常查找的表。
优点:
1、折半查找的效率比顺序查找要高。
2、折半查找的时间复杂度为log2(n)
3、折半查找的平均查找长度为log2(n+1) – 1
缺点:
1、折半查找只适用于有序表
2、折半查找限于顺序存储结构,对线性链表无法有效地进行折半查找