【转】二分查找(折半查找Binary Search)
首先给五个题目:
1.给定一个有序(不降序)的数组a[],求任意一个index使得a[index]==k,不存在则返回0.
2.给定一个有序(不降序)的数组a[],求最小的index使得a[index]==k,不存在则返回0.
3.给定 一个有序(不降序)的数组a[],求最大的index使得a[index]==k,不存在则返回0.
4.给定一个有序(不降序)的数组a[],求最大的index使得a[index]小于k,不存在则返回0.
5.给定一个有序(不降序)的数组a[],求最小的index使得a[index]大于k,不存在则返回0.
因为数组中的元素有序,因此我们采用时间复杂度较低的二分查找来做,典型的二分查找只验证是否能查找到,如果数组中存在多个k,返回不确定的任意一个index,如题目1,下面的程序中BinarySearch1,对应这种情况。
当有多个匹配时,这些值在数组中肯定连续存储(因为数组有序)。如果程序想返回某个特定的匹配,则需控制好循环结束条件,判断语句,认真分析。
本人认为,第4题与第2题相似,只需要将2题中的index-1即可。同理,第5题与第3题相似,只需将3题中的index+1即可。
下面是本人写的测试程序,考虑不周全之处,还望指正!
1 #include "stdafx.h"
2 #include <iostream>
3
4 using namespace std;
5
6 //典型的二分查找(折半查找,Binary Search),查找成功,则返回某一个
7 //匹配的下标(若有多个匹配,不确定返回哪一个),若查找不成功,返回0
8 int BinarySearch1(char *a, char k)
9 {
10 int low(0),high(0),mid(0);
11 char *p = a;
12
13 while (*p != '\0')
14 {
15 p ++;
16 high ++;
17 }
18 high --; //high为数组最后一个元素下标
19
20 while (low <= high) //注意边界条件
21 {
22 mid = low + (high - low)/2; //实际是mid = low + high,写成这种形式,是为了防止溢出
23
24 if (a[mid] == k)
25 {
26 cout << "yeah,i find it, the index is: " << mid << endl;
27 return mid;
28 }
29 else if (a[mid] > k)
30 {
31 high = mid - 1;
32 }
33 else
34 {
35 low = mid + 1;
36 }
37 }
38 cout << "sorry , i do not find it." << endl;
39 return 0;
40 }
41
42 //一个有序(不降序)的数组a[],求最小的index使得a[index]==i,不存在则返回0.
43 //如char a[] = "aaahhhhhhhyyyyzzz";,则返回最小的h的下标3.
44 char BinarySearch2(char *a, char k)
45 {
46 int low(0),high(0),mid(0);
47 char *p = a;
48
49 while (*p != '\0')
50 {
51 p ++;
52 high ++;
53 }
54 high --;
55
56 while (low < high - 1) //注意边界条件
57 {
58 mid = low + (high - low)/2; //实际是mid = low + high,写成这种形式,是为了防止溢出
59
60 if (a[mid] >= k) //当a[mid]==k时,说明已经查找到,但不一定是最小的index,
61 {
62 high = mid ;
63 }
64 else
65 {
66 low = mid;
67 }
68 }
69 if (a[low] == k) //结束时,low = high - 1,先判断a[low]是否为k
70 {
71 cout << "The index is :" << low << endl;
72 return low;
73 }
74 else if (a[high] == k)
75 {
76 cout << "The index is :" << high << endl ;
77 return high;
78 }
79 else
80 {
81 return 0;
82 }
83 }
84
85 //一个有序(不降序)的数组a[],求最大的index使得a[index]==k,不存在则返回0.
86 //如char a[] = "aaahhhhhhhyyyyzzz";,则返回最大的h的下标9.
87 char BinarySearch3(char *a, char k)
88 {
89 int low(0),high(0),mid(0);
90 char *p = a;
91
92 while (*p != '\0')
93 {
94 p ++;
95 high ++;
96 }
97 high --;
98
99 while (low < high - 1)
100 {
101 mid = low + (high - low)/2; //实际是mid = low + high,写成这种形式,是为了防止溢出
102
103 if (a[mid] <= k) //当a[mid]==k时,说明已经查找到,但不一定是最大的index,
104 {
105 low = mid ;
106 }
107 else
108 {
109 high = mid;
110 }
111 }
112 if (a[high] == k) //结束时,low = high - 1,先判断a[high]是否为k
113 {
114 cout << "The index is :" << high << endl;
115 return high;
116 }
117 else if (a[low] == k)
118 {
119 cout << "The index is :" << low << endl;
120 return low;
121 }
122 else
123 {
124 return 0;
125 }
126 }
127 int _tmain(int argc, _TCHAR* argv[])
128 {
129 char a[] = "aaahhhhhhhyyyyzzz";
130 BinarySearch1(a, 'h');
131 BinarySearch2(a, 'h');
132 BinarySearch3(a, 'h');
133 return 0;
134 }