二分查找 之初值设置的区别分析
作者:互联网
left = 0, r = v. size() - 1, while(l <= r)时
void test() {
vector<int> v{1, 3, 5, 7, 9, 11, 13, 15, 17};
vector<int> vl, vr, vm;
int find_val;
//输入要查询的值,看二分搜索下标的情况
while(cin >> find_val) {
int l = 0, r = v.size() - 1, mid;
while(l <= r) {
vl.push_back(l);
vr.push_back(r);
mid = l + ((r-l)>>1);
vm.push_back(mid);
if(v[mid] == find_val) break;
if(v[mid] > find_val) r = mid-1;
else l = mid+1;
}
//分别输出mid, l, r的运行过程中所有下标
//要找的值
cout << "f: " << find_val;
//l下标
cout << endl << "l: ";
for(int i : vl)
cout << i << " ";
cout << l;
//r下标
cout << endl << "r: ";
for(int i : vr)
cout << i << " ";
cout << r;
//mid下标
cout << endl << "m: ";
for(int i : vm)
cout << i << " ";
cout << mid << endl;
}
}
几组测试数据:
//left = 0, r = v.size() - 1, while(l <= r)
//v为要找的值,mid为下标中值,l为左下标,r为右下标
//最后一列下标值为出循环后的各下标值
//v[] = {1, 3, 5, 7, 9, 11, 13, 15, 17} 待查询数组长度为9,下标范围(0 ~ 8)
-1
f: -1
l: 0 0 0 0
r: 8 3 0 -1
m: 4 1 0 0
1
f: 1
l: 0 0 0 0
r: 8 3 0 0
m: 4 1 0 0
5
f: 5
l: 0 0 2 2
r: 8 3 3 3
m: 4 1 2 2
6
f: 6
l: 0 0 2 3 3
r: 8 3 3 3 2
m: 4 1 2 3 3
7
f: 7
l: 0 0 2 3 3
r: 8 3 3 3 3
m: 4 1 2 3 3
19
f: 19
l: 0 5 7 8 9
r: 8 8 8 8 8
m: 4 6 7 8 8
小结:
编码方式:left = 0, r = v.size() - 1, while(l <= r)
找到时:
find_val = 1(0), 7(3) 【圆括号内为下标值,用于观察下标奇偶性】
find_val的下标值:l = r = mid
find_val = 5(2)
find_val的下标值:l = mid ≠ r
所以找到 find_val 时,正确表示下标的是 l
未找到时:
当要find_val = -1小于所有的数时,r体现出未找到,且 l > r
当find_val = 19大于所有数时,l体现出未找到,且 l > r
当find_val = 6在所有数的之间却不是其中一个时,l > r
所以未找到 find_val 时,总有 l > r
换个角度:
从while(l <= r)代码块的出口这个角度来分析较简单,执行完这个代码块后,只有两种可能,要么是 l > r,要么是从mid处break: mid = (l+r)/2,r = l 或 l+1;
left = 0, r = v. size() , while(l < r)时
只需对上面代码做微调
void test() {
vector<int> v{1, 3, 5, 7, 9, 11, 13, 15, 17};
vector<int> vl, vr, vm;
int find_val;
//输入要查询的值,看二分搜索下标的情况
while(cin >> find_val) {
int l = 0, r = v.size(), mid;
while(l < r) {
vl.push_back(l);
vr.push_back(r);
mid = l + ((r-l)>>1);
vm.push_back(mid);
if(v[mid] == find_val) break;
if(v[mid] > find_val) r = mid-1;
else l = mid+1;
}
//分别输出mid, l, r的运行过程中所有下标
//要找的值
cout << "f: " << find_val;
//l下标
cout << endl << "l: ";
for(int i : vl)
cout << i << " ";
cout << l;
//r下标
cout << endl << "r: ";
for(int i : vr)
cout << i << " ";
cout << r;
//mid下标
cout << endl << "m: ";
for(int i : vm)
cout << i << " ";
cout << mid << endl;
}
}
几组测试数据:
//left = 0, r = v.size(), while(l < r)
//v为要找的值,mid为下标中值,l为左下标,r为右下标
//最后一列下标值为出循环后的各下标值
//v[] = {1, 3, 5, 7, 9, 11, 13, 15, 17} 待查询数组长度为9,下标范围(0 ~ 8)
-1
f: -1
l: 0 0 0
r: 9 3 0
m: 4 1 1
1
f: 1
l: 0 0 0
r: 9 3 0
m: 4 1 1
5
f: 5
l: 0 0 2 2
r: 9 3 3 3
m: 4 1 2 2
6
f: 6
l: 0 0 2 3
r: 9 3 3 3
m: 4 1 2 2
7
f: 7
l: 0 0 2 3
r: 9 3 3 3
m: 4 1 2 2
19
f: 19
l: 0 5 8 9
r: 9 9 9 9
m: 4 7 8 8
小结:
编码方式:left = 0, r = v.size(), while(l < r)
找到时:
find_val = 1(0), 5(2) 【圆括号内为下标值,用于观察下标奇偶性】
find_val的下标值:l = mid ≠ r
find_val = 7 (3)
find_val的下标值:l = r ≠ mid
所以找到 find_val 时,正确表示下标的是 l
未找到时:
当要find_val = -1 小于所有的数时,l = r, v[l] != find_val
当find_val = 19 大于所有数时,l = r, v[l] != find_val
当find_val = 6 在所有数的之间却不是其中一个时,l = r, v[l] != find_val
所以未找到 find_val 时,总有 l = r 且 v[l] != find_val
换个角度:
从while(l < r)代码块的出口这个角度来分析较简单,执行完这个代码块后,只有两种可能,要么是 l = r,要么是从mid处break: l < r;
标签:二分,val,初值,标值,mid,while,查找,find,size 来源: https://blog.csdn.net/github_39329077/article/details/118797901