二分查找变体

从一个循环有序的数组中查找一个元素,如果存在则返回相应位置,否则返回-1.所谓的循环有序是指类似于如下的数组
10 11 12 1 2 3 4 5 6

基础代码,供二分查找变体使用

 辅助函数
 1 //二分查找
2 int Binary_search(int a[],int beg,int end,int val)
3 {
4 while(beg<=end)
5 {
6 int mid = (beg+end)/2;
7 if(val==a[mid])
8 return mid;
9 if(val>a[mid])
10 {
11 beg = mid+1;
12 }
13 else
14 {
15 end = mid -1;
16 }
17 }
18 return -1;
19 }
20
21 //顺序查找
22 int Search(int a[],int beg,int end,int val)
23 {
24 cout<<"Search!"<<endl;
25 while(beg<=end)
26 {
27 if(a[beg]==val)
28 return beg;
29 ++beg;
30 }
31 return -1;
32 }

二分查找代变体改进版核心代码:

 第一版代码
int Binary_search(int a[],int size,int val)
{
int beg=0;
int end=size -1;
while(beg<=end)
{
int mid = (beg+end)/2;
if(val == a[mid])
return mid;
if(val>a[mid])
{
if(val<=a[end])
{
if(val == a[end])
return end;
return Binary_search(a,mid+1,end-1,val);
}
if(a[mid]>a[size-1])
{
beg =mid+1 ;
}
else if (a[mid]<a[size-1])
{
end = mid -1;
}
else
{
return Search(a,beg+1,end-1,val);
}
}
else
{
if(val>=a[beg])
{
if(val == a[beg])
return beg;
return Binary_search(a,beg+1,mid-1,val);
}

if(a[mid]>a[0])
{
beg =mid +1;
}
else if (a[mid]<a[0])
{
end = mid -1;
}
else
{
return Search(a,beg+1,end-1,val);
}
}
}
return -1;
}

改进版代码:

改进版本代码
 1 int Binary_search(int *arr,int const size,int const val)
2 {
3 if(arr[0] ==val)
4 return 0;
5 int beg =1;
6 int end = size -1;
7 int const iFirst =arr[0];
8 int const iLast = arr[size-1];
9 int const iMid = (beg+end)/2;
10 while(beg<=end)
11 {
12 int mid = (beg+end)/2;
13 if(arr[mid] == val)
14 return mid;
15
16 //左边有序,如果在左边的范围内,直接二分查找,否则到右边去找
17 if(arr[mid]>iFirst)
18 {
19 if(val>=arr[beg]&&val<arr[mid])
20 {
21 return Binary_search(arr,beg,mid-1,val);
22 }
23 beg = mid+1;
24 }
25 //右边有序,如果在右边的范围内,直接二分查找,否则在左边去找
26 else if(arr[mid]<iFirst)
27 {
28 if(val>arr[mid]&&val<=iLast)
29 {
30 return Binary_search(arr,mid+1,end,val);
31 }
32 end = mid -1;
33 }
34 else
35 {
36 //iFirst=arr[mid]>iLast左边为有序且恒等的一个序列,在右边找
37 if(arr[mid]>iLast)
38 {
39 beg = mid+1;
40 }
41 else //arr[mid]==iFirst>=iLast,arr[min]不可能小于iLast,在这里arr[min] == iLast = iFirst
42 {
43 if(mid>iMid) //iMid左边是个递增数列,arr[iMid]>arr[min];mid的右边是恒等序列
44 {
45 end = mid -1;
46 }
47 else if(mid<iMid)//iMid右边是个递增序列,arr[iMid]<arr[min],min的左边是恒等序列
48 {
49 beg = mid+1;
50 }
51 else
52 {
53 return Search(arr,beg,end,val);
54 }
55 }
56 }
57 }
58 return -1;
59 }

测试代码

测试代码
 1 #include<iostream>
2 #include <cstdlib>
3 #include <ctime>
4 #include<algorithm>
5 using namespace std;
6 void Reverse(int * beg,int *end)
7 {
8 while(beg<end)
9 {
10 swap(*beg,*end);
11 ++beg;
12 --end;
13 }
14 }
15
16 void Move(int *arr,int size, int pos)
17 {
18 Reverse(arr,arr+size-1);
19 Reverse(arr,arr+pos);
20 Reverse(arr+pos+1,arr+size-1);
21 }
22
23 void Check(int *arr,int size)
24 {
25 bool bTrue =true;
26 for(int i=1;i<size;++i)
27 {
28 if(arr[i]<arr[i-1])
29 {
30 if(!bTrue)
31 cout<<"Check Failed!"<<endl;
32 bTrue = false;
33 }
34 }
35 if(bTrue)
36 cout<<"Check Failed!"<<endl;
37 }
38 int main(int argc, char* argv[])
39 {
40 srand(time(0));
41 int const size = 10001;
42 int *arr = new int[size];
43 for(int test=0;test<1000;++test)
44 {
45 for(int i =0;i<size;++i)
46 {
47 arr[i] = rand()%100;
48 }
49 sort(arr,arr+size);
50 int pos = 1+ rand()%(size-10);
51 Move(arr,size,pos);
52 Check(arr,size);
53 for(int i=0;i<size;++i)
54 {
55 int iIndex = Binary_search(arr,size,arr[i]);
56 if(iIndex==-1)
57 {
58 cout<<"Wrong1";
59 return 0;
60 }
61 if(arr[iIndex]!=arr[i])
62 {
63 cout<<"Wrong2";
64 return 0;
65 }
66 }
67 }
68
69 return 0;
70 }




原文地址:https://www.cnblogs.com/SammyLan/p/2205904.html