1,037
社区成员




这是我参加“朝闻道”知识分享大赛的第五十九篇文章。
二分查找与三分查找:确定键值mid,mid为最左下标+最右下标的和除以2,将k与A[MID]进行比对,相等时输出结果,不相等时比较大小,判断在前半部分还是后半部分,并再次对此部分进行折半查找,当没有找到对应k时,我们通过l下标去比对其附近的值和k的值,找到其最接近的值返回。三分查找思路与二分查找相似,不同点在于键值k有2个,所以对于较大数组效率会好于二分查找。若查找元素不在数组中,需要返回最接近元素,其思路和二分查找一致。查找次数为查找键与数组元素的比较次数。
//顺序查找
int SequentialSearch(int k, int &comparisons) {
for (int i = 0; i < n; ++i) {
++comparisons;
if (arr[i] == k) {
return i;
} else if (arr[i] > k) {
// 元素不在数组中,返回最接近的元素位置
if (i == 0) {
return i;
} else {
//检查前一个元素是否更加接近
return (k - arr[i-1] <= arr[i] - k) ? i-1 : i;
}
}
}
// 元素不在数组中,返回最后一个位置
return n - 1;
}
//折半
int BinarySearch(int k,int &comparisons){
int l=0,r=n-1,mid;
while(l<r){
mid=(l+r)/2;
//cout<<mid<<endl;
comparisons++;
if(arr[mid]==k) return mid;
else if(arr[mid]>k){
r=mid-1;
}
else {
l=mid+1;
}
}
//cout<<"l"<<l<<endl;
//cout<<"r"<<r<<endl;
// 元素不在数组中,返回最接近的元素位置
if (r < 0) {
return l;
} else if (l >= n) {
return r;
} else {
// 找到最接近的元素位置
//cout<<"k - arr[l-1]:"<<k - arr[l-1]<<endl;
//cout<<"arr[l] - k:"<<arr[l] - k<<endl;
//通过l指针,如果l位置的数大于k则比较l和l-1位置的值
//否则比较l和l+1的值即可
if(arr[l]>k){
if ( k - arr[l-1] <= arr[l] - k) {
return l-1;
} else {
return l; // 否则返回当前位置 l
}
}else{
if ( k - arr[l] <= arr[l+1] - k) {
return l;
} else {
return l+1; // 否则返回当前位置 l
}
}
}
return -1;
}
// 三分查找
int TernarySearch(int k,int &comparisons) {
int l=0,r=n-1,mid1,mid2;
while (l <= r) {
int mid1 = l + (r - l) / 3;
int mid2 = r - (r - l) / 3;
//cout<<"mid1"<<mid1<<endl;
//cout<<"mid2"<<mid2<<endl;
comparisons++;
if (arr[mid1] == k) {
return mid1;
}
comparisons++;
if (arr[mid2] == k) {
return mid2;
}
comparisons++;
if (k < arr[mid1]) {
r = mid1 - 1;
} else if (k > arr[mid2]) {
l = mid2 + 1;
} else {
l = mid1 + 1;
r = mid2 - 1;
}
}
if (r < 0) {
return l;
} else if (l >= n) {
return r;
} else {
// 找到最接近的元素位置
if(arr[l]>k){
if ( k - arr[l-1] <= arr[l] - k) {
return l-1;
} else {
return l; // 否则返回当前位置 l
}
}else{
if ( k - arr[l] <= arr[l+1] - k) {
return l;
} else {
return l+1; // 否则返回当前位置 l
}
}
}
return -1;
}