二分搜索总结

来源:互联网 发布:徐州seo 编辑:程序博客网 时间:2024/05/17 22:16

编程之美上有节说各种二分的查找,于是便写了下,并给出了一些测试代码

1)二分查找元素key的下标,如无 return -1


2)二分查找返回key(可能有重复)第一次出现的下标,如无return -1

3)二分查找返回key(可能有重复)最后一次出现的下标,如无return -1

4)二分查找返回刚好小于key的元素下标,如无return -1

5)二分查找返回刚好大于key的元素下标,如无return -1

写中间有一些需要注意的地方,都在代码中写了,关键还是要处理好边界问题,下面是代码

#include <cstdio>#include <cmath>  #include <cstdlib>  // 1.二分查找元素key的下标,如无 return -1int binarySearch( int *arr, int fisrt, int last, int key ){// err check// if ( arr == NULL || fisrt > last )// return -1;// 注意查找的范围 // 左闭右开、左闭右闭int low = fisrt;int upper = last;while ( low <= upper ){int m = low + (( upper - low ) >> 1);if ( arr[m] == key ) return m;else if ( arr[m] < key )low = m + 1;   // 此处因为搜索区间所以是 m+1else upper = m - 1; // 此处因为搜索区间所以是 m-1}return -1;}// 2)二分查找返回key(可能有重复)第一次出现的下标,如无return -1int getFirstIndexOfKey( int *arr, int fisrt, int last, int key ){// err check// if ( arr == NULL || fisrt > last )// return -1;int low = fisrt;int upper = last;while ( low <= upper ){int m = low + (( upper - low ) >> 1);// 此处的关键是怎么处理 arr[m] == key// 举个例子:1 1 2 2 3//     下标:0 1 2 3 4//        m = ( 0 + 4) / 2 = 2;//    此时 arr[2] == 2,那么此时应该明确前面是否有2了,//    接着 求 [0,1] 中是否有2了,假如没有了,那结束的时候,low == upper + 1,此时查看low处是否是2,是则返回if ( key <= arr[m] )upper = m - 1;   // 当arr[m] == key 时,则 位置m 可能是第一次出现的下标else low   = m + 1;}if ( low <= last && arr[low] == key )return low;else return -1;}//3)二分查找返回key(可能有重复)最后一次出现的下标,如无return -1// 关键是处理arr[m] == key时怎么办,此时应该是找 [m+1,upper]里面是否有key了// 当没有时候时候,此时结束条件是upper=m,故此时判断是否arr[upper] == keyint getLastIndexOfKey( int *arr, int fisrt, int last, int key ){int low   = fisrt;int upper = last;while ( low <= upper ){int m = low + (( upper - low ) >> 1);if ( key >= arr[m] )low = m + 1;else upper = m - 1;}if ( upper >= fisrt && arr[upper] == key )return upper;else return -1;}//4)二分查找返回刚好小于key的元素下标,如无return -1// 分几种情况考虑// 1.假设[low,upper]中有数等于key,即arr[m] == key// 则此时应该找 [low,m-1],并假设此时是最后一个  arr[m] == key,则此时[low,m-1] < key,结束条件是low==m,返回upper即可// 2.假设[low,upper]没有key即,arr[low]<key<arr[uperr],则必然缩小到最后有 low + 1 = upper,此时结束时返回upper// 3.特殊情况考虑:key < [low,upper] , 则结束时 upper < low,返回-1// [4.low,upper] < key, 则结束时,low >upper,返回upperint binarySearchJustSmaller( int *arr, int fisrt, int last, int key ){int low   = fisrt;int upper = last;while( low <= upper ){int m = low + (( upper - low ) >> 1);if ( key <= arr[m] )upper = m - 1;else low = m + 1;}if ( upper >= fisrt || arr[upper] < key )return upper;elsereturn -1;}// 5)二分查找返回刚好大于key的元素下标,如无return -1// 分几种情况 // 1.假设[low,upper]中有数等于key,即arr[m] == key,则查找[m+1,upper],返回low即可// 2.假设[low,upper]没有key即,arr[low]<key<arr[uperr],则必然缩小到最后有 low + 1 = upper,此时结束时返回low// 3.特殊情况考虑:key < [low,upper] , 则结束时 upper < low,返回low// [4.low,upper] < key, 则结束时,low >upper,返回-1int binarySearchJusBigger( int *arr, int fisrt, int last, int key ){int low   = fisrt;int upper = last;while( low <= upper ){int m = low + (( upper - low ) >> 1);if ( arr[m] <= key )low = m + 1;else upper = m - 1;}if ( low <= last || arr[low] > key )return low;elsereturn -1;}#define GetSize(arr) ( sizeof arr / sizeof arr[0])void Test( char *name, int *arr, int size, int key, int *index ){if ( name != NULL )printf("===============%s begin===================\n",name);if ( binarySearch(arr,0,size-1,key) == index[0] )printf("binarySearch passed.\n");elseprintf("binarySearch failed.\n");if ( getFirstIndexOfKey(arr,0,size-1,key) == index[1] )printf("getFirstIndexOfKey passed.\n");elseprintf("getFirstIndexOfKey failed.\n");if ( getLastIndexOfKey(arr,0,size-1,key) == index[2] )printf("getLastIndexOfKey passed.\n");elseprintf("getLastIndexOfKey failed.\n");if ( binarySearchJustSmaller(arr,0,size-1,key) == index[3] )printf("binarySearchJustSmaller passed.\n");elseprintf("binarySearchJustSmaller failed.\n");if ( binarySearchJusBigger(arr,0,size-1,key) == index[4] )printf("binarySearchJusBigger passed.\n");elseprintf("binarySearchJusBigger failed.\n");if ( name != NULL )printf("===============%s end=================\n",name);}// 常规测试void Test1(){int arr[] = {1,2,3,4,5};int size = GetSize(arr);int index[] = {0,0,0,-1,1};Test("test1",arr,size,1,index);}void Test2(){int arr[] = {1,2,3,4,5};int size = GetSize(arr);int index[] = {1,1,1,0,2};Test("test2",arr,size,2,index);}void Test3(){int arr[] = {1,2,3,4,5};int size = GetSize(arr);int index[] = {4,4,4,3,-1};Test("test3",arr,size,5,index);}// 全都一样时void Test4(){int arr[] = {1,1,1,1,1};int size = GetSize(arr);int index[] = {2,0,4,-1,-1};Test("test4",arr,size,1,index);}// 都大void Test5(){int arr[] = {1,2,3,4,5};int size = GetSize(arr);int index[] = {-1,-1,-1,-1,0};Test("test5",arr,size,0,index);}// 都小void Test6(){int arr[] = {1,2,3,4,5};int size = GetSize(arr);int index[] = {-1,-1,-1,4,-1};Test("test6",arr,size,6,index);}void Test7(){int arr[] = {1,2,4,5,6};int size = GetSize(arr);int index[] = {-1,-1,-1,1,2};Test("test7",arr,size,3,index);}int main(){Test1();Test2();Test3();Test4();Test5();Test6();Test7();return 0;}


原创粉丝点击