下方有图片说明二分法的原理与思想(如果能找到下标(mid)最后直接指向要查找的数,但是找不到时下标(mid)有两种可能位置):
以x=7为例:
同理x=3时:
从上图可以看出 :如果没找到返回的下标mid对应的值的位置有两种可能(离x最近的左边,或离x最近的右边)
二分法的代码:
int Find_elem(int arr[],int x,int size) {
int left=0;
int right=size-1;
int mid;
while (left<=right) {//当left走到right右边是说明找不到,此时会跳出循环
mid = (left + right) / 2;
if (x > arr[mid]) {
left = mid+1;
}
else if(x<arr[mid])
{
right = mid-1;
}
else {
return mid;
}
}
return mid;
//做了一点改动无论找没找到都返回mid,
//如果没找到返回的下标mid对应的数组值有两种可能(离x最近的左边,或离x最近的右边)
}
如何将值插入数组
int index = Find_elem(arr, x, len);
if (arr[index] != x) {
for (int j = len; j > index; j--)
arr[j] = arr[j - 1];
}
这段代码运行后,会复制一个离x最近的值进入数组如运行前(假设x=7,单个数运行结果是固定的,但是换个数复制的数可能是x的上一个,也可能是x的下一个)如:2,4,6,8,10运行后有两种可能2,4,6,6,8,10或2,4,6,8,8,10具体是哪种情况与mid与x的相对位置有关(有可能在第一种情况的第一个6上,也有可能在第二种情况的第一个8上)如果是第一种情况mid下标加一才是你要插入的位置,如果是第二种情况则mid下标所在位置就是你要插入的位置,需要用下标mid(我这里用的index接收mid)对应的值与x作比较方可判断:
if (arr[index] > x) {
arr[index] = x;
}
else {
arr[index + 1] = x;
}
完整函数:
int Find_elem(int arr[],int x,int size) {
int left=0;
int right=size-1;
int mid;
while (left<=right) {//当left走到right右边是说明找不到,此时会跳出循环
mid = (left + right) / 2;
if (x > arr[mid]) {
left = mid+1;
}
else if(x<arr[mid])
{
right = mid-1;
}
else {
return mid;
}
}
return mid;
//做了一点改动无论找没找到都返回mid,
//如果没找到返回的下标mid对应的数组值有两种可能(离x最近的左边,或离x最近的右边)
}
int Find_and_insert(int arr[], int x, int len) {
int index = Find_elem(arr, x, len);
if (arr[index] != x) {
for (int j = len; j > index; j--) {
arr[j] = arr[j - 1];
}
if (arr[index] > x) {
arr[index] = x;
}
else {
arr[index + 1] = x;
}
}
}
测试代码:
int main() {
int arr[200];
int x = 15;
for (int i = 0; i < 100; i++)
{
arr[i] = i * 2;
}
Find_and_insert(arr, x, 100);
for (int i = 0; i < 100; i++)
{
printf("%d\n", arr[i]);
}
return 0;
}
毁灭吧,我累了。