数据结构笔记7:折半查找法(二分查找法)及C语言实现

折半查找,也称二分查找,在某些情况下相比于顺序查找,使用折半查找算法的效率更高。但是该算法的使用的前提是静态查找表中的数据必须是有序的。

折半查找算法

对静态查找表{5,13,19,21,37,56,64,75,80,88,92}采用折半查找算法查找关键字为 21 的过程为:
图 1 折半查找的过程(a)
如上图 1 所示,指针 low 和 high 分别指向查找表的第一个关键字和最后一个关键字,指针 mid 指向处于 low 和 high 指针中间位置的关键字。在查找的过程中每次都同 mid 指向的关键字进行比较,由于整个表中的数据是有序的,因此在比较之后就可以知道要查找的关键字的大致位置。

例如在查找关键字 21 时,首先同 56 作比较,由于21 < 56,而且这个查找表是按照升序进行排序的,所以可以判定如果静态查找表中有 21 这个关键字,就一定存在于 low 和 mid 指向的区域中间。

因此,再次遍历时需要更新 high 指针和 mid 指针的位置,令 high 指针移动到 mid 指针的左侧一个位置上,同时令 mid 重新指向 low 指针和 high 指针的中间位置。如图 2 所示:
图 2 折半查找的过程(b)
同样,用 21 同 mid 指针指向的 19 作比较,19 < 21,所以可以判定 21 如果存在,肯定处于 mid 和 high 指向的区域中。所以令 low 指向 mid 右侧一个位置上,同时更新 mid 的位置。
数据结构笔记7:折半查找法(二分查找法)及C语言实现_第1张图片
当第三次做判断时,发现 mid 就是关键字 21 ,查找结束。

注意:在做查找的过程中,如果 low 指针和 high 指针的中间位置在计算时位于两个关键字中间,即求得 mid 的位置不是整数,需要统一做取整操作。

折半查找的代码:

int BinarySearch(SeqList &L ,int x) {
	int low = 0, high = L.length - 1, mid;
	while (low<=high)
	{
		mid = (low + high) / 2;//找中间值
		if (L.data[mid]==x)//先与中间值比较
		{
			return mid;//相等就返回其值
		}
		else if (L.data[mid]<x)//如果中间值小于x,则向后半段查找
		{
			low = mid + 1;
		}
		else//如果中间值大于x,则向前半段查找
		{
			high = mid - 1;
		}
	}
	return -1;//如果没有找到,返回-1
}

折半查找的时间复杂度

分析:搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半

时间复杂度计算:

总共有n个元素。
如果知道n = 1,则t(n) = c1;

如果n > 1,则t(n) = t(n/2) + c2
其中n/2需要取整,c1、c2都是常数

第1次折半:还剩n/2个元素

第2次折半:还剩n/4个元素

第3次折半:还剩n/8个元素

……

第k次折半:还剩n/2^k个元素

最坏的情况下,最后还剩1个元素,令n/2^k = 1。得k=log2(n)。

时间复杂度O(logn)

总结

通过比较折半查找的平均查找长度,同前面介绍的顺序查找相对比,明显折半查找的效率要高。但是折半查找算法只适用于有序表,同时仅限于查找表用顺序存储结构表示。

参考文章
此文章在参考文章上做了算法的最简化和时间复杂度的分析

你可能感兴趣的:(数据结构笔记——线性表,算法,数据结构)