二分查找
1.二分查找的定义
二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。
折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
2.查找的过程
(1)假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;
(2)否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。
(3)重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
3.代码实现
(1)C和C++代码(C和C++的语法基本相同)
循环实现之第一种
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
int BinSearch(SeqList *R, int n,KeyType K) { //在有序表R[0..n-1]中进行二分查找,成功时返回结点的位置,失败时返回-1 int low=0,high=n-1,mid; //置当前查找区间上、下界的初值 while (low<=high) { if (R[low].key==K) return low; if (R[high].key==k) return high; //当前查找区间R[low..high]非空 mid=low+(high-low)/2; /*使用(low+high)/2会有整数溢出的问题 (问题会出现在当low+high的结果大于表达式结果类型所能表示的最大值时, 这样,产生溢出后再/2是不会产生正确结果的,而low+((high-low)/2) 不存在这个问题*/ if (R[mid].key==K) return mid; //查找成功返回 if (R[mid].key<K) low=mid+1; //继续在R[mid+1..high]中查找 else high=mid-1; //继续在R[low..mid-1]中查找 } if (low>high) return -1; //当low>high时表示所查找区间内没有结果,查找失败 } |
循环实现之第二种
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
int bsearchWithoutRecursion( int array[], int low, int high, int target) { while (low<=high) { int mid=low+(high-low)/2; //还是溢出问题 if (array[mid]>target) high=mid-1; else if (array[mid]<target) low=mid+1; else return mid; } return -1; } |
循环实现之第三种
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
int binSearch( const int *Array, int start, int end, int key) { int left,right; int mid; left=start; right=end; while (left<=right) { mid=left+(right-left)/2; //还是溢出问题 if (key==Array[mid]) return mid; else if (key<Array[mid]) right=mid-1; else if (key>Array[mid]) left=mid+1; } return -1; } |
递归实现(可直接编译)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
#include<iostream> using namespace std; int a[100]={1,2,3,5,12,12,12,15,29,55}; //数组中的数(由小到大) int k; //要找的数字 int found( int x, int y) { int m=x+(y-x)/2; if (x>y) //查找完毕没有找到答案,返回-1 return -1; else { if (a[m]==k) return m; //找到!返回位置. else if (a[m]>k) return found(x,m-1); //找左边 else return found(m+1,y); //找右边 } } int main() { cin>>k; //输入要找的数字c语言把cin换为scanf即可 cout<<found(0,9); //从数组a[0]到a[9]c语言把cout换为printf即可 return 0; } |
(2)Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public static int binarySearch(Integer[] srcArray, int des) { //定义初始最小、最大索引 int start = 0 ; int end = srcArray.length - 1 ; //确保不会出现重复查找,越界 while (start <= end) { //计算出中间索引值 int middle = (end + start)>>> 1 ; //防止溢出 if (des == srcArray[middle]) { return middle; //判断下限 } else if (des < srcArray[middle]) { end = middle - 1 ; //判断上限 } else { start = middle + 1 ; } } //若没有,则返回-1 return - 1 ; } |