1. 程式人生 > >c/c++ 實戰之二分查詢

c/c++ 實戰之二分查詢

二分查詢的必要條件

陣列或者集合有序,或者存在一種關係 –> 滿足條件與不滿足條件的資料能夠按照某種標準分成兩部分。最簡單的就是基本資料型別的陣列了。

比如說:我們聲明瞭一個數組 ,如下:

int array [] = {0,1,2,3,4,5,6,7,8,9,10};

假設我們要查詢這個陣列中是否存在一個值9,如果是採用for迴圈遍歷的話,那麼我們需要遍歷10次這個陣列,顯然當資料較多且我們要查詢的值有可能在陣列的尾端時,那麼這種查詢方法的效率並不高。所以機智的人類想到了這種二分查詢法,其原理也相當的簡單。
比如上面這個例子,我們在查詢陣列中是否含有9這個值時,先取陣列的中間位置,也就是index == 5的值進行判斷,如果 9 == array[5] 那麼恭喜!我們剛好查到我們想要的結果,如果9 > array[5]則說明在有序陣列中,我們要查詢的值應該位於array[5] 的右側,否則位於array[5]的左側,很明顯 9 > 5 所以,我們要查詢的值在5的右側,然後我們再取array[6] ~ array[10]的中間值查詢,即array[8],我們發現
9 > 8,那麼值還在array[8]的右側。依此類推,我們只需再查一次便可獲取到結果。對比原始的for迴圈,我們只花了3次便獲取到了結果。其效率非常之高。
下面上c++程式碼:

C++ 二分查詢實現
// CppArray.cpp : 定義控制檯應用程式的入口點。

#include "stdafx.h"     
#define GET_ARRAY_LEN(array,len) {len=sizeof(array)/sizeof(array[0]);}

//統計查詢次數    
int count = 0;

//折半查詢
int binarySearch(int* array, int start, int end, int search) {

    int median = (start + end) / 2;

    if (search < *(array + median)) {
        //因為search小於陣列中間位置的值,說明在有序陣列中要查詢的結果應該位於中間位置的值的左側
        if (median - 1 < 0)
        {
            return -1;
        }
        return binarySearch(array, start, median, search);
    }
    else if (search > *(array + median))
    {
        //因為search大於陣列中間位置的值,說明在有序陣列中要查詢的結果應該位於中間位置的值的右側
        if (median + 1 >= end)
        {
            return -1;
        }
        return binarySearch(array, median, end, search);
    }
    else
    {
        return search;
    }
}

int main()
{
    int num[] = { 0,1,2,3,4,5,6,7,8,9,10,11,12 };
    int len;
    GET_ARRAY_LEN(num, len);

    for (int i = 13; i >-3; i--)
    {
        count = 0;
        int result = binarySearch(num, 0, len, i);
        printf("查詢結果 = %d,共花了%d次\n",result, count);
    }
    return 0;
}

正如程式碼中所示,我們從13開始一直查詢到-2,結果如圖所示:
這裡寫圖片描述

我們要查詢的值最多的也才花費4次。當然對於資料不大的話使用這種查詢可能沒什麼必要,但是當資料量大的時候,比如查詢一個長度為250的陣列,那效率就不一般了,在Android中用過SparseArray或者有去了解過SparseArray具體實現的各位大佬們一定深有體會!