2014-11-23 46 views
2

假設存儲元素的容器(在這種情況下,一個普通數組)就像二進制搜索等效`find_if`

struct Foo 
    { 
    char id[8]; 
    // other members 
    }; 

現在我想找到一個Foo的ID開始於一個特定的字符串S。由於數組是按id排序的,所以我想使用二進制搜索,所以我尋找一個使用與find_if相同的接口執行二分搜索的函數。 STL中是否有這樣的函數,是否可以通過使用algorithm中的其他元素來構造,還是我需要自己實現它。

+0

爲'find_if'接口是無用的二分查找。如果這是一場比賽,那很好。但是如果謂詞表示它不匹配,那麼搜索應該在下一個當前點之前還是之後查找? – 2014-11-23 20:51:45

+0

還有一個明智的方向嗎?假設條件是'isPrime(int x)',第一個值'x'是100.現在呢? – MSalters 2014-11-24 11:12:32

+0

也許接口不完全一樣,但返回一個int指示方向。 – user877329 2014-11-24 11:18:13

回答

6

您在尋找std::lower_boundstd::upper_boundstd::equal_range,它們需要一個輸入範圍,一個搜索值和一個可選的比較器,並要求根據比較器對範圍進行排序。

爲了您的具體的例子,我會使用std::lexicographical_compare的比較:

#include <algorithm> 
#include <iterator> 

struct IdCmp 
{ 
    bool operator()(const Foo & lhs, const Foo & rhs) const 
    { 
    return std::lexicographical_compare(std::begin(lhs.id), std::end(lhs.id), 
             std::begin(rhs.id), std::end(rhs.id)); 
    } 
}; 

int main() 
{ 
    Foo a[100];   // populate 
    Foo b = make_needle(); 

    auto p = std::equal_range(std::begin(a), std::end(a), b, IdCmp()); 

    /* The elements with key equal to that of b are in [p.first, p.second). */ 
} 

如果你希望能夠直接搜索字符串,你的比較必須是可調用的異質同一個Foo參數和一個字符串參數。例如:

struct IdCmp 
{ 
    bool operator()(const Foo & lhs, const Foo & rhs) const 
    { 
    return std::lexicographical_compare(std::begin(lhs.id), std::end(lhs.id), 
             std::begin(rhs.id), std::end(rhs.id)); 
    } 

    bool operator()(const Foo & lhs, const char * id) const 
    { 
    return std::lexicographical_compare(std::begin(lhs.id), std::end(lhs.id), 
             id, id + 8); 
    } 

    bool operator()(const char * id, const Foo & rhs) const 
    { 
    return std::lexicographical_compare(id, id + 8, 
             std::begin(rhs.id), std::end(rhs.id)); 
    } 
}; 

現在您可以搜索:

std::lower_bound(std::begin(a), std::end(a), "ABCD1234", IdCmp()) 
+0

使用'id + strlen(id)'作爲lexicographical_compare的第二個參數可能更安全。但+1的一個很好的答案 – Fiktik 2014-11-23 20:56:50

+0

@Fiktik:它也慢。我想過把參數聲明爲const char(&id)[8]'。如果需要任意以空字符結尾的字符串,最好實現您自己的單遍算法。 – 2014-11-23 21:14:33

+0

@KerrekSB我只想看看字符串的開頭,所以這種方法並不能完全解決問題。 – user877329 2014-11-24 16:14:46