其他分享
首页 > 其他分享> > 二分查找 之初值设置的区别分析

二分查找 之初值设置的区别分析

作者:互联网

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