1、二分查找编程珠玑第 4 章中提到:虽然第一篇二分搜索论文在 1946 年就发表了,但是第一个没有错误的二分搜索策略却直到 1962 年才出现,由此可见二分查找思想虽然简单,但是要写好还是很难的。那二分查找会出现那么多错误,主要是因为什么原因呢?边界问题在二分查找的时候,边界很重要,需要理解查找的边界是什么?边界主要可以分为low,upper,和low ,upper) ,即左闭右开、左闭右闭。这两种情况下,代码是不一样的,其不同可以参考下面的代码1. /* 2. 输入: A 是待查找的非降序数组, n 是数据的个数,key 是查找的元素 3. 返回:没有 key,返回 -1,有返回在数据中的下标
2、 4. */ 5. int binarySearch( int *A, int n, int key ) 6. 7. int begin = 0; 8. int end = n; 9. / 0,n) 左闭右开 10. while ( begin key 18. end = mid; 19. 20. return -1; 21. 这个是左闭右开,所以当 key key 14. end = mid - 1; 15. 16. return -1; 17. 这个是左闭右闭,所以当 key end ) 5. return -1; 6. int mid = begin + ( end - begin )
3、/ 2; 7. int midData = Amid; 8. 9. if ( midData = key ) 10. 11. if ( (mid = 0) | Amid-1 != key ) 12. return mid; 13. else 14. end = mid - 1; 15. 16. else if ( midData key 19. end = mid - 1; 20. 21. return getFisrtOfK(A, begin, end, key); 22. 当我们查找到 Amid = key 的时候,此时判断前一个数是否是 key,如果不是 key,那么此时 mid 就是第
4、一个 k 出现的位置,如果是 key,那么此时范围缩小到 Abegin, mid-1,当 Amid != key 时,情况和正常情况下相似。 剑指 offer中给出的是递归的解法,下面给出非递归解法1. / A 范围是 Abegin, end为左闭右闭 2. int getFisrtOfK( int *A, int begin, int end, int key ) 3. 4. if ( A = NULL | begin end ) 5. return -1; 6. 7. int low, upper; 8. low = begin; 9. upper = end; 10. while ( l
5、ow end ) 4. return -1; 5. 6. int low, upper; 7. low = begin; 8. upper = end; 9. while ( low key 17. upper = mid - 1; 18. 19. 20. if ( upper = 0 | Aupper = key ) 21. return upper; 22. else 23. return -1; 24. 25. 当出现 midData 0) 17. 18. int first = GetFirstK(data, length, k, 0, length - 1); 19. int las
6、t = GetLastK(data, length, k, 0, length - 1); 20. 21. if(first -1 23. 24. 25. return number; 26. 27. 28./ 找到数组中第一个 k 的下标。如果数组中不存在 k,返回-1 29.int GetFirstK(int* data, int length, int k, int start, int end) 30. 31./ if(start end) 32./ return -1; 33./ 34./ int middleIndex = (start + end) / 2; 35./ int m
7、iddleData = datamiddleIndex; 36./ 37./ if(middleData = k) 38./ 39./ if(middleIndex 0 42./ else 43./ end = middleIndex - 1; 44./ 45./ else if(middleData k) 46./ end = middleIndex - 1; 47./ else 48./ start = middleIndex + 1; 49./ 50./ return GetFirstK(data, length, k, start, end); 51. if ( data = NULL
8、 | start end ) 52. return -1; 53. 54. int low, upper; 55. low = start; 56. upper = end; 57. int key = k; 58. while ( low end) 79./ return -1; 80./ 81./ int middleIndex = (start + end) / 2; 82./ int middleData = datamiddleIndex; 83./ 84./ if(middleData = k) 85./ 86./ if(middleIndex end ) 99. return -
9、1; 100. 101. int low, upper; 102. low = start; 103. upper = end; 104. int key = k; 105. while ( low key 113. upper = mid - 1; 114. 115. 116. if ( upper = 0 | dataupper = key ) 117. return upper; 118. else 119. return -1; 120. 121. 122./ =测试代码= 123.void Test(char* testName, int data, int length, int
10、k, int expected) 124. 125. if(testName != NULL) 126. printf(“%s begins: “, testName); 127. 128. int result = GetNumberOfK(data, length, k); 129. if(result = expected) 130. printf(“Passed.n“); 131. else 132. printf(“Failed.n“); 133. 134. 135./ 查找的数字出现在数组的中间 136.void Test1() 137. 138. int data = 1, 2,
11、 3, 3, 3, 3, 4, 5; 139. Test(“Test1“, data, sizeof(data) / sizeof(int), 3, 4); 140. 141. 142./ 查找的数组出现在数组的开头 143.void Test2() 144. 145. int data = 3, 3, 3, 3, 4, 5; 146. Test(“Test2“, data, sizeof(data) / sizeof(int), 3, 4); 147. 148. 149./ 查找的数组出现在数组的结尾 150.void Test3() 151. 152. int data = 1, 2, 3
12、, 3, 3, 3; 153. Test(“Test3“, data, sizeof(data) / sizeof(int), 3, 4); 154. 155. 156./ 查找的数字不存在 157.void Test4() 158. 159. int data = 1, 3, 3, 3, 3, 4, 5; 160. Test(“Test4“, data, sizeof(data) / sizeof(int), 2, 0); 161. 162. 163./ 查找的数字比第一个数字还小,不存在 164.void Test5() 165. 166. int data = 1, 3, 3, 3, 3
13、, 4, 5; 167. Test(“Test5“, data, sizeof(data) / sizeof(int), 0, 0); 168. 169. 170./ 查找的数字比最后一个数字还大,不存在 171.void Test6() 172. 173. int data = 1, 3, 3, 3, 3, 4, 5; 174. Test(“Test6“, data, sizeof(data) / sizeof(int), 6, 0); 175. 176. 177./ 数组中的数字从头到尾都是查找的数字 178.void Test7() 179. 180. int data = 3, 3,
14、3, 3; 181. Test(“Test7“, data, sizeof(data) / sizeof(int), 3, 4); 182. 183. 184./ 数组中的数字从头到尾只有一个重复的数字,不是查找的数字 185.void Test8() 186. 187. int data = 3, 3, 3, 3; 188. Test(“Test8“, data, sizeof(data) / sizeof(int), 4, 0); 189. 190. 191./ 数组中只有一个数字,是查找的数字 192.void Test9() 193. 194. int data = 3; 195. T
15、est(“Test9“, data, sizeof(data) / sizeof(int), 3, 1); 196. 197. 198./ 数组中只有一个数字,不是查找的数字 199.void Test10() 200. 201. int data = 3; 202. Test(“Test10“, data, sizeof(data) / sizeof(int), 4, 0); 203. 204. 205./ 鲁棒性测试,数组空指针 206.void Test11() 207. 208. Test(“Test11“, NULL, 0, 0, 0); 209. 210. 211.int _tmain(int argc, _TCHAR* argv) 212. 213. Test1(); 214. Test2(); 215. Test3(); 216. Test4(); 217. Test5(); 218. Test6(); 219. Test7(); 220. Test8(); 221. Test9(); 222. Test10(); 223. Test11(); 224. 225. return 0; 226.