再探二分搜索

1基本的二分搜索, 在没有重复元素的数组中查找一个元素

#include <stdio.h>

int binsearch(int a[], int t, int l, int h)
{
	int p;
	while (1)
	{
		if (l > h)
		{
			p = -1;
			break;
		}
		
		int m = (l + h) / 2;
		if (a[m] < t)
			l = m + 1;
		else if (a[m] > t)
			h = m - 1;
		else 
		{
			p = m;
			break;
		}
	}
	return p;
}

int main()
{
	int a[] = {0, 1, 2, 3, 4, 5, 7};
	printf("%d\n", binsearch(a, 2, 0, 6));
	printf("%d\n", binsearch(a, 8, 0, 6));
}
关键有以下几点:

1)循环的不变性,查找元素必须在[l, h]之间,包括l和h,而且l <= h,这个条件是进入循环就需要一直成立的

2)第一个if条件中,由于不满足第二个循环不变性,退出循环;

 第二个if条件中,a[m] < t,则t 位于 [m+1(l), h]之间,满足不变性,继续循环,第三个同理;

最后一个找到目标,退出循环

3)l 和h的范围是 l [0, n]:  0 表示l的下界, h 是 [-1, n), n-1是h的上界;而l的n和h的-1,则表示,当n =0 时,l取得0, h取得-1, 由于不满足循环的不变性,在第一个if中退出循环, l + h的范围是 [-1, 2n - 1]



2有重复元素的数组中查找重复元素的最小下标

#include <stdio.h>

int bs_duplicate(int a[], int n, int t, int l, int u)
{
	
	while (l + 1 != u)
	{
		int m = (l + u) / 2;
		if (a[m] < t)
			l = m;
		else
			u = m;
	}
	int p = u;
	if (p >= n || a[p] != t)
		p = -1;
	return p;
}

int main()
{
	int a[10] = {1,1,3,4,5,5};
	printf("%d", bs_duplicate(a, 6, 5, -1, 6));
}
1)循环的不变性 : t 属于 (l, u]中,且l < u, 这样的不变性是因为,我们需要找到仅仅有两个元素的时候,判断前一个元素比t小,后一个元素=t或者 >t, 进而找到第一次出现t的位置,否则,若第一个不变性与常规的二分查找相同,则有可能 l = t = u, 第二个不变性是要保证数组中至少有一个元素,之所以不是l = u表示数组中至少有一个元素,是因为l此时表示的不是查找范围内的下标

2)可以看到进入循环的条件比单独的l < u这一循环不变性条件更强,目的是为了定位到最终的唯一一个元素中,因此, 可以说进入循环必然满足循环不变性,而循环条件应该是某个循环不变性的子集,对于常规的二分搜索来说,循环条件与某一循环不变性相同

条件中的 循环不变性,进入循环的条件是至少有一个元素, 之后,在第一个条件中, 由于a[m] < t, 则, l = m, 满足循环不变性,而第二个条件同理

退出循环后,仍然满足循环不变性, 但是不满足循环条件,循环条件和循环不变性不同, 此时可知我们定位到唯一的一个元素啊a[u]上,由于仍然满足循环不变性, 则有 t > a[l], t <= a[ l + 1],  此时两个相邻元素a[l] 和a[l + 1] 就是我们想找到第一次出现t的方法(就是找到比t小的最大的元素), 那么此时又两种情况, 或者下一个找到比t小的之后的元素= t, 或者,之后的元素 > t,就是数组中没有t

3)l的范围是[-1, n), u的范围是[0, n]。 l + h 的范围是 [ -1, 2n - 1]。 l 的范围表示中 -1表明,因为t可能是a[0], 所以比a[0]小的下标就是-1; u的范围中, n 表示, 若t= a[n-1],则比a[n-1]大的下标就是n, 之所以有n,是因为数组中有重复元素, 所以会有 t <= a[n], 而不是常规的t < a[n].而此处,-1和n都是假想的元素下标,目的是为了与数组中元素的循环不变性相一致。当n =0 时, l 取得 -1, u取得 0, 可以看到它将由于不满足进入循环的条件而直接进入判断。

4)可以看到,以上两个二分查找的l + h的范围相同, 也就是说,求得的m的范围相同,而且[0, n - 1],  仍然满足l和h的范围。




猜你喜欢

转载自blog.csdn.net/juttajry/article/details/51233186
今日推荐