在前面的文章中介绍了对于顺序表的查找方法,从线性表中的第一个(或最后一个)数据元素开始,逐个进行数据元素关键字和给定值的比较,若某个数据元素的关键字和给定值相等则查找成功;如果直到最后一个(或第一个)数据元素,其关键字和给定值都不等时,则查找失败。
这里介绍另一种顺序表的查找方法。
二分查找 binary search
代码编写:
采用递归方式:
需要注意的是下面代码中low和high为数组的下标号,从0到size()-1。
int binary_search(int a[], int low, int high, int key) // O(log2 n)
//采用递归方式,二分查找,a为查找的数组,low和high为两个端点序号,key为要查找的值
{
int ret = -1;
if( low <= high )
{
int mid = (low + high) / 2;
if( a[mid] == key )
{
ret = mid;
}
else if( key < a[mid] )
{
ret = binary_search(a, low, mid-1, key);
}
else if( key > a[mid] )
{
ret = binary_search(a, mid+1, high, key);
}
}
return ret;
}
不采用递归方式,耗时少:
int binary_search_ex(int a[], int low, int high, int key) // O(log2n)
//二分查找,a为查找的数组,low和high为两个端点序号,key为要查找的值
{
int ret = -1;
while( low <= high )
{
int mid = (low + high) / 2;
if( a[mid] == key )
{
ret = mid;
break;
}
else if( key < a[mid] )
{
high = mid - 1;
}
else if( key > a[mid] )
{
low = mid + 1;
}
}
return ret;
}
插值查找 interpolation search
在二分查找中,mid固定的为(high+low)/2,这在某些情况下会增加程序运行的时间,降低效率。因此提出了插值查找。
插值查找的mid的查找方法如下所示:
但是应当注意:
也就是: a[low] <= key <= a[high]
代码编写:
int interpolation_search(int a[], int low, int high, int key)
//插值查找,a为查找的数组,low和high为两个端点序号,key为要查找的值
{
int ret = -1;
while( (low <= high) && (a[low] <= key) && (key <= a[high]) )
{
float fx = 1.0f * (key - a[low]) / (a[high] - a[low]);
int mid = low + fx * (high - low);
if( a[mid] == key )
{
ret = mid;
break;
}
else if( key < a[mid] )
{
high = mid - 1;
}
else if( key > a[mid] )
{
low = mid + 1;
}
}
return ret;
}
小结
顺序查找比较土,但却是其他查找算法的基础。
二分查找基于有序的线性表,时间复杂度为O(log2 n)。
二分查找可以根据需要进一步演变为插值查找。