在n个记录的有序顺序表中进行折半查找,查找过程落在对应判定树的第i层的某个外部结点中,则关键字的比较次数是
为什么不是i呀他在i层
i 是怎么使用的?每次折半时传 i 的地址并在折半方法里 *i++
AB(A代表前i个元素,B代表后n-i个元素),先将A置换,在将B置换,最后将AB置换
AB -> A-1B -> A-1B-1 -> BA
算法如下:
#include <stdio.h>
void foreMove(int* a, int path, int n);
void reverse(int* a, int m, int n);
int main(void){
int a[7] = {3,5,7,9,11,13,66};
int i;
foreMove(a, 5, 7);
for(i=0; i<7; i++){
printf("%d ",a[i]);
}
return 0;
}
void foreMove(int* a, int path, int n){
reverse(a, 0, path-1);
reverse(a, path, n-1);
reverse(a, 0, n-1);
}
void reverse(int* a, int m, int n){
int temp;
while( m<n ){
temp = *(a+m);
*(a+m) = *(a+n);
*(a+n) = temp;
m++;
n--;
}
}
结果
需移动 i/2 + (n-i)/2 + n/2 = n 次数组单元
需1个临时交换存储单元
折半查找是一种常用的搜索算法,应用于对有序表进行查找。它通过比较中间位置关键字与查找关键字来确定下一步查找的区域,将查找区域缩小一半,直到找到目标为止。但是,如果查找过程落在对应判定树的第i层的某个外部结点中,关键字的比较次数应该是Log2(i+1)而不是i次。因为折半查找的搜索过程是不断将查找区域缩小一半,而不是对每个结点进行比较。具体的解决方案如下:
解决方案: 1. 折半查找算法 折半查找算法实现如下:
int BinarySearch(int arr[], int left, int right, int x) {
if(left > right) {
return -1;
}
int mid = left + (right - left) / 2; //求中间位置
if(arr[mid] == x) {
return mid;
} else if(arr[mid] > x) {
return BinarySearch(arr, left, mid - 1, x);
} else {
return BinarySearch(arr, mid + 1, right, x);
}
}
其中,left表示左边界,right表示右边界,x表示要查找的元素,mid表示中间位置。通过这个算法,可以快速查找到对应元素。
在折半查找中,每一次比较都会将待查区间缩小为原来的一半,因此需要的比较次数最多为判定树的深度k。对于普通的二叉查找树,其深度最差可达到n,而对于平衡二叉查找树,则可以对高度作出限制,将查找时间复杂度控制在Log2n以内。
因此,在折半查找中,如果查找过程落在对应判定树的第i层的某个外部结点中,则该节点编号的有效位数为i,因此需要进行Log2(i+1)次比较,而不是i次。
下面是对折半查找优化后的代码:
int BinarySearch(int arr[], int left, int right, int x) {
if(left > right) {
return -1;
}
int mid = left + (right - left) / 2; //求中间位置
if(arr[mid] == x) {
return mid;
} else if(arr[mid] > x) {
return BinarySearch(arr, left, mid - 1, x);
} else {
return BinarySearch(arr, mid + 1, right, x);
}
}
int main() {
int arr[] = {4, 7, 8, 9, 13, 15, 20};
int n = sizeof(arr) / sizeof(arr[0]);
int x = 13;
int res = BinarySearch(arr, 0, n - 1, x);
if(res == -1) {
cout << "未找到元素" << endl;
} else {
cout << "元素" << x << "的位置为" << res << endl;
}
return 0;
}