二分查找法
算法思想
以如下代码块为例:
int low = 0;
int high = list->length;
int mid = 0;
//二分查找
while (low <= high) {
mid = (low + high) / 2;//这里可以使用位移
// mid = (low + high) >> 1;
if (list->data[mid] == target) {
break;
}
if (list->data[mid] > target) {
high = mid - 1;
} else {
low = mid + 1;
}
}
代码比较简单,主要的要点就是:
- 要遍历的数组 [或者容器] 必须是有序的
- 每次遍历时,根据
mid
这个指向的数值数组[mid]
来判断数组 [mid]
>target:说明边界可以往左缩小,high=mid-1
数组 [mid]
<=target:说明边界可以往右扩大,low=mid+1
- 最后的边界条件是:
low<=high
这个可以看如下动图 - 当数组中无查找元素时
- 数组为升序时:
- 此时
height
>low
,且height
会停留在比target
小的数的左边,即如果你想要插入一个target
并且是数组仍然是升序的 1,那你需要把height
之后的元素 [不包括 height] 都向后移一位,之后在令数组[height+1]=target;
即可
例题
bool binarySearchAndReplace(SqList *list, int target) {
int low = 0;
int high = list->length;
int mid = 0;
//二分查找
while (low <= high) {
mid = (low + high) / 2;//这里可以使用位移
// mid = (low + high) >> 1;
if (list->data[mid] == target) {
break;
}
if (list->data[mid] > target) {
high = mid - 1;
} else {
low = mid + 1;
}
}
//替换
//数值与目标相等且不是末尾元素
if (list->data[mid]==target && mid != list->length - 1) {
int temp = list->data[mid];
list->data[mid] = list->data[mid + 1];
list->data[mid + 1] = temp;
}
//如果未找到,插入目标值并且是数组为有序
if (low > high) {
int i = 0;
for (i = list->length - 1; i > high; --i) {
list->data[i + 1] = list->data[i];
}
list->data[high+1] = target;
list->length++;
}
return true;
}
数组项后移推荐: 从逆序遍历,从数组最后一个元素开始位移,[前移则从 0 开始] ↩︎