資料結構與演算法——二分查詢演算法

readyao發表於2016-01-06
在一個無序的資料序列中查詢某一個數值,我們只能遍歷該序列的每一個數值,並與要查詢的數值比較。時間複雜度為O(N)。
在有序排序(假定從小到大)的資料序列中查詢某一個數值,沒有必要遍歷每一個數值。我們可以用二分查詢。

基本思路是:

將序列的中間值和val比較,如果data[mid]大於val,則說明序列中在data[mid]右邊的資料都大於val。所以我們只能在data[mid]的左邊查詢。這樣我們就將比較範圍縮小了一半。每次比較我們都可以將範圍縮小一半。該演算法的時間複雜度為O(logN)。

原始碼:

/*************************************************************************
	> File Name: bin_search.cpp
	> Author: 
	> Mail: 
	> Created Time: 2016年01月06日 星期三 13時09分47秒
 ************************************************************************/

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

void input_data(vector<int> & data)
{
    cout << "輸入資料:";
    int tmp;
    while(cin >> tmp && tmp != -10000){
        data.push_back(tmp);
    }
}

void output_data(vector<int> & data)
{
    cout << "輸入的資料: ";
    for (vector<int>::iterator it = data.begin(); it != data.end(); ++it){
        cout << *it << " ";
    }
    cout << endl;
}
int bin_search(vector<int> & data, int val)
{
    int low = 0, high = data.size()-1;
    int mid;

    while(low <= high){
        mid = (low + high)/2;
        if(data[mid] < val)
            low = mid + 1;
        else if(data[mid] > val)
            high = mid - 1;
        else
            return mid;
    }
    return data.size();
}

int main()
{
    vector<int> data;
    input_data(data);
    //排序
    cin.get();
    sort(data.begin(), data.end());
    //輸入要查詢的資料
    output_data(data);
    int val;
    cout << "輸入要查詢的資料: ";
    cin >> val;
    int index = bin_search(data, val);
    if(index == data.size()){
        cout << "index = " << index << ", data doesn't have " << val << endl;
        return 0;
    }
    cout << "index = " << index << ", data[index] = " << data[index] << endl;
    return 0;
}


下面是二分查詢的遞迴實現:

/*************************************************************************
	> File Name: binarySearch.cpp
	> Author: 
	> Mail: 
	> Created Time: 2016年04月16日 星期六 19時47分10秒
 ************************************************************************/

#include <iostream>
#include <time.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
using namespace std;


//二分查詢
int binarySearch(vector<int> & v, int first, int last, int value)
{
    int half = (first+last)/2;

    if(v[half] == value)
        return half;
    else if(v[half] < value)
        return binarySearch(v, half, last, value);
    else
        return binarySearch(v, 0, half, value);

}


//主函式
int main()
{
    srand(unsigned(time(0)));

    vector<int> v;

    for(int i = 0; i < 10; ++i)
        v.push_back(rand()%10);

    sort(v.begin(), v.end());//排序

    cout << "v: ";
    for(int i = 0; i < 10; ++i)
        cout << v[i] << " ";
    cout << endl;

    int val = v[rand()%10];

    int index = binarySearch(v, 0, v.size()-1, val);
    cout << val << " index is " << index << endl;


    return 0;
}

//二分查詢
int binarySearch(vector<int> & v, int first, int last, int value)
{
     if(first < last)
	return;//沒有找到則返回,之前忘了找不到的情況。。
	//今天面試寫程式碼被面試官發現了。還是面試官厲害。

    int half = (first+last)/2;

    if(v[half] == value)
        return half;
    else if(v[half] < value)
        return binarySearch(v, half, last, value);
    else
        return binarySearch(v, 0, half, value);

}

執行結果:

v: 0 0 2 2 2 3 6 6 8 8 
2 index is 4
root@linux_ever:~/linux_ever/algorithm/ch7# ./binarySearch 
v: 1 1 1 1 2 6 7 7 9 9 
7 index is 6
root@linux_ever:~/linux_ever/algorithm/ch7# ./binarySearch 
v: 0 0 0 2 2 5 5 7 8 9 
7 index is 7
root@linux_ever:~/linux_ever/algorithm/ch7# ./binarySearch 
v: 0 0 0 2 2 5 5 7 8 9 
7 index is 7
root@linux_ever:~/linux_ever/algorithm/ch7# ./binarySearch 
v: 0 0 1 2 5 5 6 7 8 8 
5 index is 4
root@linux_ever:~/linux_ever/algorithm/ch7# ./binarySearch 
v: 0 0 1 2 5 5 6 7 8 8 
5 index is 4
root@linux_ever:~/linux_ever/algorithm/ch7# ./binarySearch 
v: 0 0 1 1 3 6 7 9 9 9 
9 index is 7
root@linux_ever:~/linux_ever/algorithm/ch7# ./binarySearch 
v: 0 0 1 1 3 6 7 9 9 9 
9 index is 7

相關文章